diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 25d921b7cea4c..0155803e30580 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -205,26 +205,24 @@ pub struct LocalTableInContext<'a, V> { fn validate_hir_id_for_typeck_tables(local_id_root: Option, hir_id: hir::HirId, mut_access: bool) { - if cfg!(debug_assertions) { - if let Some(local_id_root) = local_id_root { - if hir_id.owner != local_id_root.index { - ty::tls::with(|tcx| { - bug!("node {} with HirId::owner {:?} cannot be placed in \ - TypeckTables with local_id_root {:?}", - tcx.hir().node_to_string(hir_id), - DefId::local(hir_id.owner), - local_id_root) - }); - } - } else { - // We use "Null Object" TypeckTables in some of the analysis passes. - // These are just expected to be empty and their `local_id_root` is - // `None`. Therefore we cannot verify whether a given `HirId` would - // be a valid key for the given table. Instead we make sure that - // nobody tries to write to such a Null Object table. - if mut_access { - bug!("access to invalid TypeckTables") - } + if let Some(local_id_root) = local_id_root { + if hir_id.owner != local_id_root.index { + ty::tls::with(|tcx| { + bug!("node {} with HirId::owner {:?} cannot be placed in \ + TypeckTables with local_id_root {:?}", + tcx.hir().node_to_string(hir_id), + DefId::local(hir_id.owner), + local_id_root) + }); + } + } else { + // We use "Null Object" TypeckTables in some of the analysis passes. + // These are just expected to be empty and their `local_id_root` is + // `None`. Therefore we cannot verify whether a given `HirId` would + // be a valid key for the given table. Instead we make sure that + // nobody tries to write to such a Null Object table. + if mut_access { + bug!("access to invalid TypeckTables") } } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 21ea4766d8e52..c3975098351af 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -370,7 +370,8 @@ impl UnusedParens { right_pos: Option) { match value.node { ast::ExprKind::Paren(ref inner) => { - if !Self::is_expr_parens_necessary(inner, followed_by_block) { + if !Self::is_expr_parens_necessary(inner, followed_by_block) && + value.attrs.is_empty() { let expr_text = if let Ok(snippet) = cx.sess().source_map() .span_to_snippet(value.span) { snippet diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 12c5ce12a0e8b..55f6b91e71431 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -130,6 +130,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.save_ctxt.span_from_span(span) } + fn lookup_def_id(&self, ref_id: NodeId) -> Option { + self.save_ctxt.lookup_def_id(ref_id) + } + pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) { let source_file = self.tcx.sess.local_crate_source_file.as_ref(); let crate_root = source_file.map(|source_file| { @@ -223,13 +227,6 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } } - fn lookup_def_id(&self, ref_id: NodeId) -> Option { - match self.save_ctxt.get_path_res(ref_id) { - Res::PrimTy(..) | Res::SelfTy(..) | Res::Err => None, - def => Some(def.def_id()), - } - } - fn process_formals(&mut self, formals: &'l [ast::Param], qualname: &str) { for arg in formals { self.visit_pat(&arg.pat); @@ -283,36 +280,32 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ) { debug!("process_method: {}:{}", id, ident); - if let Some(mut method_data) = self.save_ctxt.get_method_data(id, ident, span) { - let sig_str = crate::make_signature(&sig.decl, &generics); - if body.is_some() { - self.nest_tables( - id, - |v| v.process_formals(&sig.decl.inputs, &method_data.qualname), - ); - } + let hir_id = self.tcx.hir().node_to_hir_id(id); + self.nest_tables(id, |v| { + if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) { + v.process_formals(&sig.decl.inputs, &method_data.qualname); + v.process_generic_params(&generics, &method_data.qualname, id); - self.process_generic_params(&generics, &method_data.qualname, id); + method_data.value = crate::make_signature(&sig.decl, &generics); + method_data.sig = sig::method_signature(id, ident, generics, sig, &v.save_ctxt); - method_data.value = sig_str; - method_data.sig = sig::method_signature(id, ident, generics, sig, &self.save_ctxt); - let hir_id = self.tcx.hir().node_to_hir_id(id); - self.dumper.dump_def(&access_from_vis!(self.save_ctxt, vis, hir_id), method_data); - } + v.dumper.dump_def(&access_from_vis!(v.save_ctxt, vis, hir_id), method_data); + } - // walk arg and return types - for arg in &sig.decl.inputs { - self.visit_ty(&arg.ty); - } + // walk arg and return types + for arg in &sig.decl.inputs { + v.visit_ty(&arg.ty); + } - if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output { - self.visit_ty(ret_ty); - } + if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output { + v.visit_ty(ret_ty); + } - // walk the fn body - if let Some(body) = body { - self.nest_tables(id, |v| v.visit_block(body)); - } + // walk the fn body + if let Some(body) = body { + v.visit_block(body); + } + }); } fn process_struct_field_def(&mut self, field: &ast::StructField, parent_id: NodeId) { @@ -377,26 +370,31 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ty_params: &'l ast::Generics, body: &'l ast::Block, ) { - if let Some(fn_data) = self.save_ctxt.get_item_data(item) { - down_cast_data!(fn_data, DefData, item.span); - self.nest_tables( - item.id, - |v| v.process_formals(&decl.inputs, &fn_data.qualname), - ); - self.process_generic_params(ty_params, &fn_data.qualname, item.id); - let hir_id = self.tcx.hir().node_to_hir_id(item.id); - self.dumper.dump_def(&access_from!(self.save_ctxt, item, hir_id), fn_data); - } + let hir_id = self.tcx.hir().node_to_hir_id(item.id); + self.nest_tables(item.id, |v| { + if let Some(fn_data) = v.save_ctxt.get_item_data(item) { + down_cast_data!(fn_data, DefData, item.span); + v.process_formals(&decl.inputs, &fn_data.qualname); + v.process_generic_params(ty_params, &fn_data.qualname, item.id); - for arg in &decl.inputs { - self.visit_ty(&arg.ty); - } + v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), fn_data); + } - if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { - self.visit_ty(&ret_ty); - } + for arg in &decl.inputs { + v.visit_ty(&arg.ty) + } + + if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { + if let ast::TyKind::ImplTrait(..) = ret_ty.node { + // FIXME: Opaque type desugaring prevents us from easily + // processing trait bounds. See `visit_ty` for more details. + } else { + v.visit_ty(&ret_ty); + } + } - self.nest_tables(item.id, |v| v.visit_block(&body)); + v.visit_block(&body); + }); } fn process_static_or_const_item( @@ -1113,11 +1111,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. - for bound in bounds.iter() { - if let ast::GenericBound::Trait(trait_ref, _) = bound { - self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path) - } - } + self.process_bounds(&bounds); } ast::ImplItemKind::Macro(_) => {} } @@ -1364,10 +1358,10 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ty); self.process_generic_params(ty_params, &qualname, item.id); } - OpaqueTy(ref _bounds, ref ty_params) => { + OpaqueTy(ref bounds, ref ty_params) => { let qualname = format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id))); - // FIXME do something with _bounds + let value = String::new(); if !self.span.filter_generated(item.ident.span) { let span = self.span_from_span(item.ident.span); @@ -1393,6 +1387,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { ); } + self.process_bounds(bounds); self.process_generic_params(ty_params, &qualname, item.id); } Mac(_) => (), @@ -1449,6 +1444,18 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(element); self.nest_tables(length.id, |v| v.visit_expr(&length.value)); } + ast::TyKind::ImplTrait(id, ref bounds) => { + // FIXME: As of writing, the opaque type lowering introduces + // another DefPath scope/segment (used to declare the resulting + // opaque type item). + // However, the synthetic scope does *not* have associated + // typeck tables, which means we can't nest it and we fire an + // assertion when resolving the qualified type paths in trait + // bounds... + // This will panic if called on return type `impl Trait`, which + // we guard against in `process_fn`. + self.nest_tables(id, |v| v.process_bounds(bounds)); + } _ => visit::walk_ty(self, t), } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 4bc098db68611..055ccf6c2c4f8 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -312,7 +312,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { let impl_id = self.next_impl_id(); let span = self.span_from_span(sub_span); - let type_data = self.lookup_ref_id(typ.id); + let type_data = self.lookup_def_id(typ.id); type_data.map(|type_data| { Data::RelationData(Relation { kind: RelationKind::Impl { @@ -322,7 +322,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { from: id_from_def_id(type_data), to: trait_ref .as_ref() - .and_then(|t| self.lookup_ref_id(t.ref_id)) + .and_then(|t| self.lookup_def_id(t.ref_id)) .map(id_from_def_id) .unwrap_or_else(|| null_id()), }, @@ -495,7 +495,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } pub fn get_trait_ref_data(&self, trait_ref: &ast::TraitRef) -> Option { - self.lookup_ref_id(trait_ref.ref_id).and_then(|def_id| { + self.lookup_def_id(trait_ref.ref_id).and_then(|def_id| { let span = trait_ref.path.span; if generated_code(span) { return None; @@ -870,7 +870,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { }) } - fn lookup_ref_id(&self, ref_id: NodeId) -> Option { + fn lookup_def_id(&self, ref_id: NodeId) -> Option { match self.get_path_res(ref_id) { Res::PrimTy(_) | Res::SelfTy(..) | Res::Err => None, def => Some(def.def_id()), diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index b14e02a2cb478..b5265fe369e83 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1956,7 +1956,8 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// # Platform-specific behavior /// /// This function currently corresponds to the `opendir` function on Unix -/// and the `FindFirstFile` function on Windows. +/// and the `FindFirstFile` function on Windows. Advancing the iterator +/// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows. /// Note that, this [may change in the future][changes]. /// /// [changes]: ../io/index.html#platform-specific-behavior diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/issue-54538-unused-parens-lint.rs index 1d8cce5228116..7dcbdd0863cbd 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.rs +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.rs @@ -1,4 +1,4 @@ -#![feature(box_patterns)] +#![feature(box_patterns, stmt_expr_attributes)] #![feature(or_patterns)] //~^ WARN the feature `or_patterns` is incomplete @@ -17,6 +17,10 @@ fn lint_on_top_level() { let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern } +fn _no_lint_attr() { + let _x = #[allow(dead_code)] (1 + 2); +} + // Don't lint in these cases (#64106). fn or_patterns_no_lint() { match Box::new(0) { diff --git a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr index 7d5e286416fe2..675dd4f07def6 100644 --- a/src/test/ui/lint/issue-54538-unused-parens-lint.stderr +++ b/src/test/ui/lint/issue-54538-unused-parens-lint.stderr @@ -49,109 +49,109 @@ LL | let _ = |(a): u8| 0; | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:41:12 + --> $DIR/issue-54538-unused-parens-lint.rs:45:12 | LL | if let (0 | 1) = 0 {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:42:13 + --> $DIR/issue-54538-unused-parens-lint.rs:46:13 | LL | if let ((0 | 1),) = (0,) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:43:13 + --> $DIR/issue-54538-unused-parens-lint.rs:47:13 | LL | if let [(0 | 1)] = [0] {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:44:16 + --> $DIR/issue-54538-unused-parens-lint.rs:48:16 | LL | if let 0 | (1 | 2) = 0 {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:46:15 + --> $DIR/issue-54538-unused-parens-lint.rs:50:15 | LL | if let TS((0 | 1)) = TS(0) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:48:20 + --> $DIR/issue-54538-unused-parens-lint.rs:52:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:58:9 + --> $DIR/issue-54538-unused-parens-lint.rs:62:9 | LL | (_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:59:9 + --> $DIR/issue-54538-unused-parens-lint.rs:63:9 | LL | (y) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:60:9 + --> $DIR/issue-54538-unused-parens-lint.rs:64:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:61:9 + --> $DIR/issue-54538-unused-parens-lint.rs:65:9 | LL | (e @ 1...2) => {} | ^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:67:9 + --> $DIR/issue-54538-unused-parens-lint.rs:71:9 | LL | (e @ &(1...2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:68:10 + --> $DIR/issue-54538-unused-parens-lint.rs:72:10 | LL | &(_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:79:9 + --> $DIR/issue-54538-unused-parens-lint.rs:83:9 | LL | (_) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:80:9 + --> $DIR/issue-54538-unused-parens-lint.rs:84:9 | LL | (y) => {} | ^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:81:9 + --> $DIR/issue-54538-unused-parens-lint.rs:85:9 | LL | (ref r) => {} | ^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:82:9 + --> $DIR/issue-54538-unused-parens-lint.rs:86:9 | LL | (e @ 1..=2) => {} | ^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:88:9 + --> $DIR/issue-54538-unused-parens-lint.rs:92:9 | LL | (e @ &(1..=2)) => {} | ^^^^^^^^^^^^^^ help: remove these parentheses error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:89:10 + --> $DIR/issue-54538-unused-parens-lint.rs:93:10 | LL | &(_) => {} | ^^^ help: remove these parentheses diff --git a/src/test/ui/save-analysis/issue-63663.rs b/src/test/ui/save-analysis/issue-63663.rs new file mode 100644 index 0000000000000..92e85884f664d --- /dev/null +++ b/src/test/ui/save-analysis/issue-63663.rs @@ -0,0 +1,28 @@ +// check-pass +// compile-flags: -Zsave-analysis + +pub trait Trait { + type Assoc; +} + +pub struct A; + +trait Generic {} +impl Generic for () {} + +// Don't ICE when resolving type paths in return type `impl Trait` +fn assoc_in_opaque_type_bounds() -> impl Generic {} + +// Check that this doesn't ICE when processing associated const in formal +// argument and return type of functions defined inside function/method scope. +pub fn func() { + fn _inner1(_: U::Assoc) {} + fn _inner2() -> U::Assoc { unimplemented!() } + + impl A { + fn _inner1(self, _: U::Assoc) {} + fn _inner2(self) -> U::Assoc { unimplemented!() } + } +} + +fn main() {}