diff options
| author | bors <bors@rust-lang.org> | 2023-04-07 20:40:05 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-04-07 20:40:05 +0000 |
| commit | 23ee2af2f7669d521ad39ef8a506a4fa3d37ea5a (patch) | |
| tree | ab7f04e9497bcabd5cc654a4df0d86bc9afa8265 /compiler | |
| parent | da636956dd13638a5582f9dcd4699559d85ac2d5 (diff) | |
| parent | d5b1ef1c3f5f5fae73baee4b463e264842c8a73d (diff) | |
| download | rust-23ee2af2f7669d521ad39ef8a506a4fa3d37ea5a.tar.gz rust-23ee2af2f7669d521ad39ef8a506a4fa3d37ea5a.zip | |
Auto merge of #109788 - compiler-errors:trait-item-from-non-trait, r=petrochenkov
More descriptive error when qself path doesnt have a trait on the RHS of `as` `<Ty as Enum>::Assoc` should report that `Enum` is a trait. Main question is whether to eagerly report the error, or raise it with `return Err(..)` -- i'll note that in an inline comment though. cc `@GuillaumeGomez` who said this came up at a Paris Rust meetup. r? `@petrochenkov`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 19f46d45af6..b1a696d093e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -122,6 +122,12 @@ pub(crate) enum ConstantItemKind { Static, } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +enum RecordPartialRes { + Yes, + No, +} + /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] @@ -2682,6 +2688,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &path, PathSource::Trait(AliasPossibility::No), Finalize::new(trait_ref.ref_id, trait_ref.path.span), + RecordPartialRes::Yes, ); self.diagnostic_metadata.currently_processing_impl_trait = None; if let Some(def_id) = res.expect_full_res().opt_def_id() { @@ -3420,6 +3427,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &Segment::from_path(path), source, Finalize::new(id, path.span), + RecordPartialRes::Yes, ); } @@ -3430,6 +3438,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { path: &[Segment], source: PathSource<'ast>, finalize: Finalize, + record_partial_res: RecordPartialRes, ) -> PartialRes { let ns = source.namespace(); @@ -3636,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { _ => report_errors(self, None), }; - if !matches!(source, PathSource::TraitItem(..)) { + if record_partial_res == RecordPartialRes::Yes { // Avoid recording definition of `A::B` in `<T as A>::B::C`. self.r.record_partial_res(node_id, partial_res); self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); @@ -3740,7 +3749,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ))); } - // Make sure `A::B` in `<T as A::B>::C` is a trait item. + let num_privacy_errors = self.r.privacy_errors.len(); + // Make sure that `A` in `<T as A>::B::C` is a trait. + let trait_res = self.smart_resolve_path_fragment( + &None, + &path[..qself.position], + PathSource::Trait(AliasPossibility::No), + Finalize::new(finalize.node_id, qself.path_span), + RecordPartialRes::No, + ); + + if trait_res.expect_full_res() == Res::Err { + return Ok(Some(trait_res)); + } + + // Truncate additional privacy errors reported above, + // because they'll be recomputed below. + self.r.privacy_errors.truncate(num_privacy_errors); + + // Make sure `A::B` in `<T as A>::B::C` is a trait item. // // Currently, `path` names the full item (`A::B::C`, in // our example). so we extract the prefix of that that is @@ -3753,6 +3780,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &path[..=qself.position], PathSource::TraitItem(ns), Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span), + RecordPartialRes::No, ); // The remaining segments (the `C` in our example) will |
