Skip to content

Commit

Permalink
Poison check_well_formed if method receivers are invalid to prevent t…
Browse files Browse the repository at this point in the history
…ypeck from running on it
  • Loading branch information
oli-obk committed Oct 30, 2023
1 parent 6d1fc53 commit 8020f97
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 17 deletions.
36 changes: 23 additions & 13 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
f: F,
) -> Result<(), ErrorGuaranteed>
where
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> Result<(), ErrorGuaranteed>,
{
let param_env = tcx.param_env(body_def_id);
let infcx = &tcx.infer_ctxt().build();
Expand All @@ -105,7 +105,7 @@ where
if !tcx.features().trivial_bounds {
wfcx.check_false_global_bounds()
}
f(&mut wfcx);
f(&mut wfcx)?;

let assumed_wf_types = wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)?;

Expand Down Expand Up @@ -875,6 +875,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
ty,
trait_def_id,
);
Ok(())
})
} else {
let mut diag = match ty.kind() {
Expand Down Expand Up @@ -956,6 +957,8 @@ fn check_associated_item(
ty::ImplContainer => tcx.type_of(item.container_id(tcx)).instantiate_identity(),
};

let mut res = Ok(());

match item.kind {
ty::AssocKind::Const => {
let ty = tcx.type_of(item.def_id).instantiate_identity();
Expand All @@ -972,7 +975,7 @@ fn check_associated_item(
hir_sig.decl,
item.def_id.expect_local(),
);
check_method_receiver(wfcx, hir_sig, item, self_ty);
res = res.and(check_method_receiver(wfcx, hir_sig, item, self_ty));
}
ty::AssocKind::Type => {
if let ty::AssocItemContainer::TraitContainer = item.container {
Expand All @@ -985,6 +988,7 @@ fn check_associated_item(
}
}
}
res
})
}

Expand Down Expand Up @@ -1097,6 +1101,7 @@ fn check_type_defn<'tcx>(
}

check_where_clauses(wfcx, item.span, item.owner_id.def_id);
Ok(())
})
}

Expand All @@ -1121,7 +1126,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
}

let res = enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
check_where_clauses(wfcx, item.span, def_id)
check_where_clauses(wfcx, item.span, def_id);
Ok(())
});

// Only check traits, don't check trait aliases
Expand Down Expand Up @@ -1164,6 +1170,7 @@ fn check_item_fn(
enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
let sig = tcx.fn_sig(def_id).instantiate_identity();
check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
Ok(())
})
}

Expand Down Expand Up @@ -1218,6 +1225,7 @@ fn check_item_type(
tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
);
}
Ok(())
})
}

Expand Down Expand Up @@ -1276,6 +1284,7 @@ fn check_impl<'tcx>(
}

check_where_clauses(wfcx, item.span, item.owner_id.def_id);
Ok(())
})
}

Expand Down Expand Up @@ -1548,11 +1557,11 @@ fn check_method_receiver<'tcx>(
fn_sig: &hir::FnSig<'_>,
method: ty::AssocItem,
self_ty: Ty<'tcx>,
) {
) -> Result<(), ErrorGuaranteed> {
let tcx = wfcx.tcx();

if !method.fn_has_self_parameter {
return;
return Ok(());
}

let span = fn_sig.decl.inputs[0].span;
Expand All @@ -1571,11 +1580,11 @@ fn check_method_receiver<'tcx>(
if tcx.features().arbitrary_self_types {
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
// Report error; `arbitrary_self_types` was enabled.
e0307(tcx, span, receiver_ty);
return Err(e0307(tcx, span, receiver_ty));
}
} else {
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, false) {
if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
return Err(if receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
// Report error; would have worked with `arbitrary_self_types`.
feature_err(
&tcx.sess.parse_sess,
Expand All @@ -1587,16 +1596,17 @@ fn check_method_receiver<'tcx>(
),
)
.help(HELP_FOR_SELF_TYPE)
.emit();
.emit()
} else {
// Report error; would not have worked with `arbitrary_self_types`.
e0307(tcx, span, receiver_ty);
}
e0307(tcx, span, receiver_ty)
});
}
}
Ok(())
}

fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) {
fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed {
struct_span_err!(
tcx.sess.diagnostic(),
span,
Expand All @@ -1605,7 +1615,7 @@ fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) {
)
.note("type of `self` must be `Self` or a type that dereferences to it")
.help(HELP_FOR_SELF_TYPE)
.emit();
.emit()
}

/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/self/arbitrary-self-from-method-substs.default.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
--> $DIR/arbitrary-self-from-method-substs.rs:8:43
|
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
| ^
|
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
= help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/arbitrary-self-from-method-substs.rs:14:5
--> $DIR/arbitrary-self-from-method-substs.rs:16:5
|
LL | foo.get::<&Foo>();
| ^^^ expected `&Foo`, found `Foo`
Expand Down
8 changes: 5 additions & 3 deletions tests/ui/self/arbitrary-self-from-method-substs.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
#![feature(arbitrary_self_types)]
// revisions: default feature
#![cfg_attr(feature, feature(arbitrary_self_types))]

use std::ops::Deref;

struct Foo(u32);
impl Foo {
fn get<R: Deref<Target=Self>>(self: R) -> u32 {
fn get<R: Deref<Target = Self>>(self: R) -> u32 {
//[default]~^ ERROR: `R` cannot be used as the type of `self`
self.0
}
}

fn main() {
let mut foo = Foo(1);
foo.get::<&Foo>();
//~^ ERROR mismatched types
//[feature]~^ ERROR mismatched types
}

0 comments on commit 8020f97

Please sign in to comment.