diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7cd0cd1ebcdc4..8a1a6c6f41916 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2210,6 +2210,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx)) } + fn lower_res_for_universal_param_and_bounds( + &mut self, + def_id: LocalDefId, + pred: &Option>, + ) -> Res { + if let Some(predicate) = pred + && let hir::WherePredicate::BoundPredicate(bound_pred) = predicate + && bound_pred.bounds.iter().any(|bound| { + let mut references_error = false; + if let hir::GenericBound::Trait(poly) = bound { + for segment in poly.trait_ref.path.segments { + for arg in segment.args().args { + if let hir::GenericArg::Type(ty) = arg + && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind + && let Res::Err = path.res + { + references_error = true; + break; + } + } + } + } + references_error + }) + { + // When any of the arguments of an `impl Trait` couldn't be resolved, we mark + // the type parameter corresponding to the `impl Trait` as `Err` in order to avoid + // knock down errors, particularly in trait selection, as if `A` isn't resolved, + // `impl Trait: Trait` *doesn't* hold. + Res::Err + } else { + Res::Def(DefKind::TyParam, def_id.to_def_id()) + } + } + #[instrument(level = "debug", skip(self), ret)] fn lower_universal_param_and_bounds( &mut self, @@ -2246,7 +2281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ); let hir_id = self.next_id(); - let res = Res::Def(DefKind::TyParam, def_id.to_def_id()); + let res = self.lower_res_for_universal_param_and_bounds(def_id, &preds); let ty = hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { diff --git a/tests/ui/impl-trait/resolve-error-in-impl-trait-fn-argument.rs b/tests/ui/impl-trait/resolve-error-in-impl-trait-fn-argument.rs new file mode 100644 index 0000000000000..f2325434f6778 --- /dev/null +++ b/tests/ui/impl-trait/resolve-error-in-impl-trait-fn-argument.rs @@ -0,0 +1,9 @@ +// Ensure that we don't emit an E0270 for "`impl AsRef: AsRef` not satisfied". + +fn foo(filename: impl AsRef) { //~ ERROR cannot find type `Path` in this scope + std::fs::write(filename, "hello").unwrap(); +} + +fn main() { + foo("/tmp/hello"); +} diff --git a/tests/ui/impl-trait/resolve-error-in-impl-trait-fn-argument.stderr b/tests/ui/impl-trait/resolve-error-in-impl-trait-fn-argument.stderr new file mode 100644 index 0000000000000..ea6f159670b69 --- /dev/null +++ b/tests/ui/impl-trait/resolve-error-in-impl-trait-fn-argument.stderr @@ -0,0 +1,14 @@ +error[E0412]: cannot find type `Path` in this scope + --> $DIR/resolve-error-in-impl-trait-fn-argument.rs:3:29 + | +LL | fn foo(filename: impl AsRef) { + | ^^^^ not found in this scope + | +help: consider importing this struct + | +LL + use std::path::Path; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0412`.