Skip to content

Commit 759e07f

Browse files
committed
Auto merge of #132361 - jieyouxu:rollup-zburkwr, r=jieyouxu
Rollup of 6 pull requests Successful merges: - #130098 (Reject generic self types.) - #131096 (rustdoc: Remove usage of `allow(unused)` attribute on `no_run` merged doctests) - #132315 (compiletest: improve robustness of LLVM version handling) - #132346 (Some graphviz tweaks) - #132359 (Fix AIX libc call char type from i8 to u8) - #132360 (Un-vacation myself) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 298c746 + 5209757 commit 759e07f

29 files changed

+836
-186
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,7 @@ dependencies = [
720720
"miropt-test-tools",
721721
"regex",
722722
"rustfix",
723+
"semver",
723724
"serde",
724725
"serde_json",
725726
"tracing",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
The `self` parameter in a method has an invalid generic "receiver type".
2+
3+
Erroneous code example:
4+
5+
```compile_fail,E0801
6+
struct Foo;
7+
8+
impl Foo {
9+
fn foo<R: std::ops::Deref<Target=Self>>(self: R) {}
10+
}
11+
```
12+
13+
or alternatively,
14+
15+
```compile_fail,E0801
16+
struct Foo;
17+
18+
impl Foo {
19+
fn foo(self: impl std::ops::Deref<Target=Self>) {}
20+
}
21+
```
22+
23+
Methods take a special first parameter, termed `self`. It's normal to
24+
use `self`, `&self` or `&mut self`, which are syntactic sugar for
25+
`self: Self`, `self: &Self`, and `self: &mut Self` respectively.
26+
But it's also possible to use more sophisticated types of `self`
27+
parameter, for instance `std::rc::Rc<Self>`. The set of allowable
28+
`Self` types is extensible using the nightly feature
29+
[Arbitrary self types][AST].
30+
This will extend the valid set of `Self` types to anything which implements
31+
`std::ops::Deref<Target=Self>`, for example `Rc<Self>`, `Box<Self>`, or
32+
your own smart pointers that do the same.
33+
34+
However, even with that feature, the `self` type must be concrete.
35+
Generic `self` types are not permitted. Specifically, a `self` type will
36+
be rejected if it is a type parameter defined on the method.
37+
38+
These are OK:
39+
40+
```
41+
struct Foo;
42+
43+
impl Foo {
44+
fn foo(self) {}
45+
fn foo2(self: std::rc::Rc<Self>) {} // or some other similar
46+
// smart pointer if you enable arbitrary self types and
47+
// the pointer implements Deref<Target=Self>
48+
}
49+
```
50+
51+
[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html

compiler/rustc_error_codes/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ E0797: 0797,
540540
E0798: 0798,
541541
E0799: 0799,
542542
E0800: 0800,
543+
E0801: 0801,
543544
);
544545
)
545546
}

compiler/rustc_hir_analysis/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
234234
.help = consider moving this inherent impl into the crate defining the type if possible
235235
.span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
236236
237+
hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
238+
.note = type of `self` must not be a method generic parameter type
239+
240+
hir_analysis_invalid_generic_receiver_ty_help =
241+
use a concrete type such as `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`)
242+
237243
hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}`
238244
.note = type of `self` must be `Self` or a type that dereferences to it
239245

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+52-9
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,6 @@ fn check_impl_item<'tcx>(
904904
hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
905905
_ => (None, impl_item.span),
906906
};
907-
908907
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
909908
}
910909

@@ -1725,8 +1724,11 @@ fn check_method_receiver<'tcx>(
17251724
} else {
17261725
None
17271726
};
1727+
let generics = tcx.generics_of(method.def_id);
17281728

1729-
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
1729+
let receiver_validity =
1730+
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
1731+
if let Err(receiver_validity_err) = receiver_validity {
17301732
return Err(match arbitrary_self_types_level {
17311733
// Wherever possible, emit a message advising folks that the features
17321734
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
@@ -1737,7 +1739,9 @@ fn check_method_receiver<'tcx>(
17371739
receiver_ty,
17381740
self_ty,
17391741
Some(ArbitrarySelfTypesLevel::Basic),
1740-
) =>
1742+
generics,
1743+
)
1744+
.is_ok() =>
17411745
{
17421746
// Report error; would have worked with `arbitrary_self_types`.
17431747
feature_err(
@@ -1759,7 +1763,9 @@ fn check_method_receiver<'tcx>(
17591763
receiver_ty,
17601764
self_ty,
17611765
Some(ArbitrarySelfTypesLevel::WithPointers),
1762-
) =>
1766+
generics,
1767+
)
1768+
.is_ok() =>
17631769
{
17641770
// Report error; would have worked with `arbitrary_self_types_pointers`.
17651771
feature_err(
@@ -1777,13 +1783,45 @@ fn check_method_receiver<'tcx>(
17771783
_ =>
17781784
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
17791785
{
1780-
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
1786+
match receiver_validity_err {
1787+
ReceiverValidityError::DoesNotDeref => {
1788+
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
1789+
}
1790+
ReceiverValidityError::MethodGenericParamUsed => {
1791+
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
1792+
}
1793+
}
17811794
}
17821795
});
17831796
}
17841797
Ok(())
17851798
}
17861799

1800+
/// Error cases which may be returned from `receiver_is_valid`. These error
1801+
/// cases are generated in this function as they may be unearthed as we explore
1802+
/// the `autoderef` chain, but they're converted to diagnostics in the caller.
1803+
enum ReceiverValidityError {
1804+
/// The self type does not get to the receiver type by following the
1805+
/// autoderef chain.
1806+
DoesNotDeref,
1807+
/// A type was found which is a method type parameter, and that's not allowed.
1808+
MethodGenericParamUsed,
1809+
}
1810+
1811+
/// Confirms that a type is not a type parameter referring to one of the
1812+
/// method's type params.
1813+
fn confirm_type_is_not_a_method_generic_param(
1814+
ty: Ty<'_>,
1815+
method_generics: &ty::Generics,
1816+
) -> Result<(), ReceiverValidityError> {
1817+
if let ty::Param(param) = ty.kind() {
1818+
if (param.index as usize) >= method_generics.parent_count {
1819+
return Err(ReceiverValidityError::MethodGenericParamUsed);
1820+
}
1821+
}
1822+
Ok(())
1823+
}
1824+
17871825
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
17881826
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
17891827
/// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled.
@@ -1799,7 +1837,8 @@ fn receiver_is_valid<'tcx>(
17991837
receiver_ty: Ty<'tcx>,
18001838
self_ty: Ty<'tcx>,
18011839
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
1802-
) -> bool {
1840+
method_generics: &ty::Generics,
1841+
) -> Result<(), ReceiverValidityError> {
18031842
let infcx = wfcx.infcx;
18041843
let tcx = wfcx.tcx();
18051844
let cause =
@@ -1811,9 +1850,11 @@ fn receiver_is_valid<'tcx>(
18111850
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
18121851
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
18131852
}) {
1814-
return true;
1853+
return Ok(());
18151854
}
18161855

1856+
confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
1857+
18171858
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
18181859

18191860
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
@@ -1830,6 +1871,8 @@ fn receiver_is_valid<'tcx>(
18301871
potential_self_ty, self_ty
18311872
);
18321873

1874+
confirm_type_is_not_a_method_generic_param(potential_self_ty, method_generics)?;
1875+
18331876
// Check if the self type unifies. If it does, then commit the result
18341877
// since it may have region side-effects.
18351878
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
@@ -1838,7 +1881,7 @@ fn receiver_is_valid<'tcx>(
18381881
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
18391882
}) {
18401883
wfcx.register_obligations(autoderef.into_obligations());
1841-
return true;
1884+
return Ok(());
18421885
}
18431886

18441887
// Without `feature(arbitrary_self_types)`, we require that each step in the
@@ -1865,7 +1908,7 @@ fn receiver_is_valid<'tcx>(
18651908
}
18661909

18671910
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
1868-
false
1911+
Err(ReceiverValidityError::DoesNotDeref)
18691912
}
18701913

18711914
fn receiver_is_implemented<'tcx>(

compiler/rustc_hir_analysis/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1623,6 +1623,16 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
16231623
pub receiver_ty: Ty<'tcx>,
16241624
}
16251625

1626+
#[derive(Diagnostic)]
1627+
#[diag(hir_analysis_invalid_generic_receiver_ty, code = E0801)]
1628+
#[note]
1629+
#[help(hir_analysis_invalid_generic_receiver_ty_help)]
1630+
pub(crate) struct InvalidGenericReceiverTy<'tcx> {
1631+
#[primary_span]
1632+
pub span: Span,
1633+
pub receiver_ty: Ty<'tcx>,
1634+
}
1635+
16261636
#[derive(Diagnostic)]
16271637
#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
16281638
#[note]

compiler/rustc_hir_typeck/src/method/confirm.rs

-3
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
533533
self.register_predicates(obligations);
534534
}
535535
Err(terr) => {
536-
// FIXME(arbitrary_self_types): We probably should limit the
537-
// situations where this can occur by adding additional restrictions
538-
// to the feature, like the self type can't reference method args.
539536
if self.tcx.features().arbitrary_self_types() {
540537
self.err_ctxt()
541538
.report_mismatched_types(

0 commit comments

Comments
 (0)