diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index fdca6d0e17a1d..7cae74b59c7f9 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -191,7 +191,7 @@ rustc_queries! { /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). - query inferred_outlives_of(_: DefId) -> &'tcx [ty::Predicate<'tcx>] {} + query inferred_outlives_of(_: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] {} /// Maps from the `DefId` of a trait to the list of /// super-predicates. This is a subset of the full list of diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 4696d4da58ec0..2734fce4ea55a 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -378,15 +378,21 @@ fn orphan_check_trait_ref<'tcx>( // Let Ti be the first such type. // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti) // - fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec> { - if fundamental_ty(ty) { - ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect() + fn uncover_fundamental_ty<'a>( + tcx: TyCtxt<'_>, + ty: Ty<'a>, + in_crate: InCrate, + ) -> Vec> { + if fundamental_ty(ty) && !ty_is_local(tcx, ty, in_crate) { + ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)).collect() } else { vec![ty] } } - for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) { + for input_ty in + trait_ref.input_types().flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate)) + { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4660e8025d48e..8807f3f8ed357 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1138,7 +1138,7 @@ pub struct CratePredicatesMap<'tcx> { /// For each struct with outlive bounds, maps to a vector of the /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. - pub predicates: FxHashMap]>, + pub predicates: FxHashMap, Span)]>, } impl<'tcx> AsRef> for Predicate<'tcx> { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 15adf7e4add73..6e8bc11162f66 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -106,8 +106,6 @@ pub fn abort_on_err(result: Result, sess: &Session) -> T { pub trait Callbacks { /// Called before creating the compiler instance fn config(&mut self, _config: &mut interface::Config) {} - /// Called early during compilation to allow other drivers to easily register lints. - fn extra_lints(&mut self, _ls: &mut lint::LintStore) {} /// Called after parsing. Return value instructs the compiler whether to /// continue the compilation afterwards (defaults to `Compilation::Continue`) fn after_parsing(&mut self, _compiler: &interface::Compiler) -> Compilation { diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ad674911e6f33..7c19449f96b86 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1497,10 +1497,10 @@ declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMEN impl ExplicitOutlivesRequirements { fn lifetimes_outliving_lifetime<'tcx>( - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], index: u32, ) -> Vec> { - inferred_outlives.iter().filter_map(|pred| { + inferred_outlives.iter().filter_map(|(pred, _)| { match pred { ty::Predicate::RegionOutlives(outlives) => { let outlives = outlives.skip_binder(); @@ -1517,10 +1517,10 @@ impl ExplicitOutlivesRequirements { } fn lifetimes_outliving_type<'tcx>( - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], index: u32, ) -> Vec> { - inferred_outlives.iter().filter_map(|pred| { + inferred_outlives.iter().filter_map(|(pred, _)| { match pred { ty::Predicate::TypeOutlives(outlives) => { let outlives = outlives.skip_binder(); @@ -1539,7 +1539,7 @@ impl ExplicitOutlivesRequirements { &self, param: &'tcx hir::GenericParam, tcx: TyCtxt<'tcx>, - inferred_outlives: &'tcx [ty::Predicate<'tcx>], + inferred_outlives: &'tcx [(ty::Predicate<'tcx>, Span)], ty_generics: &'tcx ty::Generics, ) -> Vec> { let index = ty_generics.param_def_id_to_index[ diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0dc9f91ae00e1..08554c83ed5bf 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -197,6 +197,13 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { return TAG_INVALID_SPAN.encode(self) } + // HACK(eddyb) there's no way to indicate which crate a Span is coming + // from right now, so decoding would fail to find the SourceFile if + // it's not local to the crate the Span is found in. + if self.source_file_cache.is_imported() { + return TAG_INVALID_SPAN.encode(self) + } + TAG_VALID_SPAN.encode(self)?; span.lo.encode(self)?; @@ -379,6 +386,7 @@ impl<'tcx> EncodeContext<'tcx> { .filter(|source_file| { // No need to re-export imported source_files, as any downstream // crate will import them from their original source. + // FIXME(eddyb) the `Span` encoding should take that into account. !source_file.is_imported() }) .map(|source_file| { diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index f2aef2c12c7df..9ad63f28a8e16 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -578,7 +578,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Trait(..) | - hir::ItemKind::Impl(..) => self.tcx.sess.source_map().def_span(item.span), + hir::ItemKind::Impl(..) => item.ident.span, _ => item.span, }; let participle = match item.kind { diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 136ab1f0444fa..9b254ab7ec1a2 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -316,22 +316,8 @@ impl<'a> PathSource<'a> { } } -struct LateResolutionVisitor<'a, 'b> { - r: &'b mut Resolver<'a>, - - /// The module that represents the current item scope. - parent_scope: ParentScope<'a>, - - /// The current set of local scopes for types and values. - /// FIXME #4948: Reuse ribs to avoid allocation. - ribs: PerNS>>, - - /// The current set of local scopes, for labels. - label_ribs: Vec>, - - /// The trait that the current context can refer to. - current_trait_ref: Option<(Module<'a>, TraitRef)>, - +#[derive(Default)] +struct DiagnosticMetadata { /// The current trait's associated types' ident, used for diagnostic suggestions. current_trait_assoc_types: Vec, @@ -350,6 +336,29 @@ struct LateResolutionVisitor<'a, 'b> { /// Only used for better errors on `fn(): fn()`. current_type_ascription: Vec, + + /// Only used for better errors on `let : ;`. + current_let_binding: Option<(Span, Option, Option)>, +} + +struct LateResolutionVisitor<'a, 'b> { + r: &'b mut Resolver<'a>, + + /// The module that represents the current item scope. + parent_scope: ParentScope<'a>, + + /// The current set of local scopes for types and values. + /// FIXME #4948: Reuse ribs to avoid allocation. + ribs: PerNS>>, + + /// The current set of local scopes, for labels. + label_ribs: Vec>, + + /// The trait that the current context can refer to. + current_trait_ref: Option<(Module<'a>, TraitRef)>, + + /// Fields used to add information to diagnostic errors. + diagnostic_metadata: DiagnosticMetadata, } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. @@ -373,7 +382,18 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { self.resolve_expr(expr, None); } fn visit_local(&mut self, local: &'tcx Local) { + let local_spans = match local.pat.kind { + // We check for this to avoid tuple struct fields. + PatKind::Wild => None, + _ => Some(( + local.pat.span, + local.ty.as_ref().map(|ty| ty.span), + local.init.as_ref().map(|init| init.span), + )), + }; + let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans); self.resolve_local(local); + self.diagnostic_metadata.current_let_binding = original; } fn visit_ty(&mut self, ty: &'tcx Ty) { match ty.kind { @@ -415,7 +435,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { } } fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, sp: Span, _: NodeId) { - let previous_value = replace(&mut self.current_function, Some(sp)); + let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp)); debug!("(resolving function) entering function"); let rib_kind = match fn_kind { FnKind::ItemFn(..) => FnItemRibKind, @@ -441,7 +461,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { debug!("(resolving function) leaving function"); }) }); - self.current_function = previous_value; + self.diagnostic_metadata.current_function = previous_value; } fn visit_generics(&mut self, generics: &'tcx Generics) { @@ -475,7 +495,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { // (We however cannot ban `Self` for defaults on *all* generic // lists; e.g. trait generics can usefully refer to `Self`, // such as in the case of `trait Add`.) - if self.current_self_item.is_some() { // (`Some` if + only if we are in ADT's generics.) + if self.diagnostic_metadata.current_self_item.is_some() { + // (`Some` if + only if we are in ADT's generics.) default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err); } @@ -527,12 +548,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { }, label_ribs: Vec::new(), current_trait_ref: None, - current_trait_assoc_types: Vec::new(), - current_self_type: None, - current_self_item: None, - current_function: None, - unused_labels: Default::default(), - current_type_ascription: Vec::new(), + diagnostic_metadata: DiagnosticMetadata::default(), } } @@ -892,16 +908,22 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn with_current_self_type(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T { // Handle nested impls (inside fn bodies) - let previous_value = replace(&mut self.current_self_type, Some(self_type.clone())); + let previous_value = replace( + &mut self.diagnostic_metadata.current_self_type, + Some(self_type.clone()), + ); let result = f(self); - self.current_self_type = previous_value; + self.diagnostic_metadata.current_self_type = previous_value; result } fn with_current_self_item(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T { - let previous_value = replace(&mut self.current_self_item, Some(self_item.id)); + let previous_value = replace( + &mut self.diagnostic_metadata.current_self_item, + Some(self_item.id), + ); let result = f(self); - self.current_self_item = previous_value; + self.diagnostic_metadata.current_self_item = previous_value; result } @@ -912,14 +934,14 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { f: impl FnOnce(&mut Self) -> T, ) -> T { let trait_assoc_types = replace( - &mut self.current_trait_assoc_types, + &mut self.diagnostic_metadata.current_trait_assoc_types, trait_items.iter().filter_map(|item| match &item.kind { TraitItemKind::Type(bounds, _) if bounds.len() == 0 => Some(item.ident), _ => None, }).collect(), ); let result = f(self); - self.current_trait_assoc_types = trait_assoc_types; + self.diagnostic_metadata.current_trait_assoc_types = trait_assoc_types; result } @@ -1746,7 +1768,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn with_resolved_label(&mut self, label: Option