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
This commit is contained in:
bors 2024-10-30 17:14:47 +00:00
commit 759e07f063
29 changed files with 836 additions and 186 deletions

View File

@ -720,6 +720,7 @@ dependencies = [
"miropt-test-tools",
"regex",
"rustfix",
"semver",
"serde",
"serde_json",
"tracing",

View File

@ -0,0 +1,51 @@
The `self` parameter in a method has an invalid generic "receiver type".
Erroneous code example:
```compile_fail,E0801
struct Foo;
impl Foo {
fn foo<R: std::ops::Deref<Target=Self>>(self: R) {}
}
```
or alternatively,
```compile_fail,E0801
struct Foo;
impl Foo {
fn foo(self: impl std::ops::Deref<Target=Self>) {}
}
```
Methods take a special first parameter, termed `self`. It's normal to
use `self`, `&self` or `&mut self`, which are syntactic sugar for
`self: Self`, `self: &Self`, and `self: &mut Self` respectively.
But it's also possible to use more sophisticated types of `self`
parameter, for instance `std::rc::Rc<Self>`. The set of allowable
`Self` types is extensible using the nightly feature
[Arbitrary self types][AST].
This will extend the valid set of `Self` types to anything which implements
`std::ops::Deref<Target=Self>`, for example `Rc<Self>`, `Box<Self>`, or
your own smart pointers that do the same.
However, even with that feature, the `self` type must be concrete.
Generic `self` types are not permitted. Specifically, a `self` type will
be rejected if it is a type parameter defined on the method.
These are OK:
```
struct Foo;
impl Foo {
fn foo(self) {}
fn foo2(self: std::rc::Rc<Self>) {} // or some other similar
// smart pointer if you enable arbitrary self types and
// the pointer implements Deref<Target=Self>
}
```
[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html

View File

@ -540,6 +540,7 @@ E0797: 0797,
E0798: 0798,
E0799: 0799,
E0800: 0800,
E0801: 0801,
);
)
}

View File

@ -234,6 +234,12 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
.help = consider moving this inherent impl into the crate defining the type if possible
.span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
.note = type of `self` must not be a method generic parameter type
hir_analysis_invalid_generic_receiver_ty_help =
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`)
hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}`
.note = type of `self` must be `Self` or a type that dereferences to it

View File

@ -904,7 +904,6 @@ fn check_impl_item<'tcx>(
hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
_ => (None, impl_item.span),
};
check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig)
}
@ -1725,8 +1724,11 @@ fn check_method_receiver<'tcx>(
} else {
None
};
let generics = tcx.generics_of(method.def_id);
if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level) {
let receiver_validity =
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
if let Err(receiver_validity_err) = receiver_validity {
return Err(match arbitrary_self_types_level {
// Wherever possible, emit a message advising folks that the features
// `arbitrary_self_types` or `arbitrary_self_types_pointers` might
@ -1737,7 +1739,9 @@ fn check_method_receiver<'tcx>(
receiver_ty,
self_ty,
Some(ArbitrarySelfTypesLevel::Basic),
) =>
generics,
)
.is_ok() =>
{
// Report error; would have worked with `arbitrary_self_types`.
feature_err(
@ -1759,7 +1763,9 @@ fn check_method_receiver<'tcx>(
receiver_ty,
self_ty,
Some(ArbitrarySelfTypesLevel::WithPointers),
) =>
generics,
)
.is_ok() =>
{
// Report error; would have worked with `arbitrary_self_types_pointers`.
feature_err(
@ -1777,13 +1783,45 @@ fn check_method_receiver<'tcx>(
_ =>
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
{
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
match receiver_validity_err {
ReceiverValidityError::DoesNotDeref => {
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
}
ReceiverValidityError::MethodGenericParamUsed => {
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
}
}
}
});
}
Ok(())
}
/// Error cases which may be returned from `receiver_is_valid`. These error
/// cases are generated in this function as they may be unearthed as we explore
/// the `autoderef` chain, but they're converted to diagnostics in the caller.
enum ReceiverValidityError {
/// The self type does not get to the receiver type by following the
/// autoderef chain.
DoesNotDeref,
/// A type was found which is a method type parameter, and that's not allowed.
MethodGenericParamUsed,
}
/// Confirms that a type is not a type parameter referring to one of the
/// method's type params.
fn confirm_type_is_not_a_method_generic_param(
ty: Ty<'_>,
method_generics: &ty::Generics,
) -> Result<(), ReceiverValidityError> {
if let ty::Param(param) = ty.kind() {
if (param.index as usize) >= method_generics.parent_count {
return Err(ReceiverValidityError::MethodGenericParamUsed);
}
}
Ok(())
}
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
/// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled.
@ -1799,7 +1837,8 @@ fn receiver_is_valid<'tcx>(
receiver_ty: Ty<'tcx>,
self_ty: Ty<'tcx>,
arbitrary_self_types_enabled: Option<ArbitrarySelfTypesLevel>,
) -> bool {
method_generics: &ty::Generics,
) -> Result<(), ReceiverValidityError> {
let infcx = wfcx.infcx;
let tcx = wfcx.tcx();
let cause =
@ -1811,9 +1850,11 @@ fn receiver_is_valid<'tcx>(
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
}) {
return true;
return Ok(());
}
confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?;
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty);
// The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`.
@ -1830,6 +1871,8 @@ fn receiver_is_valid<'tcx>(
potential_self_ty, self_ty
);
confirm_type_is_not_a_method_generic_param(potential_self_ty, method_generics)?;
// Check if the self type unifies. If it does, then commit the result
// since it may have region side-effects.
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
@ -1838,7 +1881,7 @@ fn receiver_is_valid<'tcx>(
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
}) {
wfcx.register_obligations(autoderef.into_obligations());
return true;
return Ok(());
}
// Without `feature(arbitrary_self_types)`, we require that each step in the
@ -1865,7 +1908,7 @@ fn receiver_is_valid<'tcx>(
}
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
false
Err(ReceiverValidityError::DoesNotDeref)
}
fn receiver_is_implemented<'tcx>(

View File

@ -1623,6 +1623,16 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
pub receiver_ty: Ty<'tcx>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_invalid_generic_receiver_ty, code = E0801)]
#[note]
#[help(hir_analysis_invalid_generic_receiver_ty_help)]
pub(crate) struct InvalidGenericReceiverTy<'tcx> {
#[primary_span]
pub span: Span,
pub receiver_ty: Ty<'tcx>,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_cmse_inputs_stack_spill, code = E0798)]
#[note]

View File

@ -533,9 +533,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
self.register_predicates(obligations);
}
Err(terr) => {
// FIXME(arbitrary_self_types): We probably should limit the
// situations where this can occur by adding additional restrictions
// to the feature, like the self type can't reference method args.
if self.tcx.features().arbitrary_self_types() {
self.err_ctxt()
.report_mismatched_types(

View File

@ -32,8 +32,11 @@ pub(crate) struct Formatter<'mir, 'tcx, A>
where
A: Analysis<'tcx>,
{
body: &'mir Body<'tcx>,
results: RefCell<Option<Results<'tcx, A>>>,
// The `RefCell` is used because `<Formatter as Labeller>::node_label`
// takes `&self`, but it needs to modify the cursor. This is also the
// reason for the `Formatter`/`BlockFormatter` split; `BlockFormatter` has
// the operations that involve the mutation, i.e. within the `borrow_mut`.
cursor: RefCell<ResultsCursor<'mir, 'tcx, A>>,
style: OutputStyle,
reachable: BitSet<BasicBlock>,
}
@ -48,11 +51,15 @@ where
style: OutputStyle,
) -> Self {
let reachable = mir::traversal::reachable_as_bitset(body);
Formatter { body, results: Some(results).into(), style, reachable }
Formatter { cursor: results.into_results_cursor(body).into(), style, reachable }
}
fn body(&self) -> &'mir Body<'tcx> {
self.cursor.borrow().body()
}
pub(crate) fn into_results(self) -> Results<'tcx, A> {
self.results.into_inner().unwrap()
self.cursor.into_inner().into_results()
}
}
@ -81,7 +88,7 @@ where
type Edge = CfgEdge;
fn graph_id(&self) -> dot::Id<'_> {
let name = graphviz_safe_def_name(self.body.source.def_id());
let name = graphviz_safe_def_name(self.body().source.def_id());
dot::Id::new(format!("graph_for_def_id_{name}")).unwrap()
}
@ -90,20 +97,11 @@ where
}
fn node_label(&self, block: &Self::Node) -> dot::LabelText<'_> {
let mut label = Vec::new();
self.results.replace_with(|results| {
// `Formatter::result` is a `RefCell<Option<_>>` so we can replace
// the value with `None`, move it into the results cursor, move it
// back out, and return it to the refcell wrapped in `Some`.
let mut fmt = BlockFormatter {
results: results.take().unwrap().into_results_cursor(self.body),
style: self.style,
bg: Background::Light,
};
let mut cursor = self.cursor.borrow_mut();
let mut fmt =
BlockFormatter { cursor: &mut cursor, style: self.style, bg: Background::Light };
let label = fmt.write_node_label(*block).unwrap();
fmt.write_node_label(&mut label, *block).unwrap();
Some(fmt.results.into_results())
});
dot::LabelText::html(String::from_utf8(label).unwrap())
}
@ -112,12 +110,12 @@ where
}
fn edge_label(&self, e: &Self::Edge) -> dot::LabelText<'_> {
let label = &self.body[e.source].terminator().kind.fmt_successor_labels()[e.index];
let label = &self.body()[e.source].terminator().kind.fmt_successor_labels()[e.index];
dot::LabelText::label(label.clone())
}
}
impl<'mir, 'tcx, A> dot::GraphWalk<'mir> for Formatter<'mir, 'tcx, A>
impl<'tcx, A> dot::GraphWalk<'_> for Formatter<'_, 'tcx, A>
where
A: Analysis<'tcx>,
{
@ -125,7 +123,7 @@ where
type Edge = CfgEdge;
fn nodes(&self) -> dot::Nodes<'_, Self::Node> {
self.body
self.body()
.basic_blocks
.indices()
.filter(|&idx| self.reachable.contains(idx))
@ -134,10 +132,10 @@ where
}
fn edges(&self) -> dot::Edges<'_, Self::Edge> {
self.body
.basic_blocks
let body = self.body();
body.basic_blocks
.indices()
.flat_map(|bb| dataflow_successors(self.body, bb))
.flat_map(|bb| dataflow_successors(body, bb))
.collect::<Vec<_>>()
.into()
}
@ -147,20 +145,20 @@ where
}
fn target(&self, edge: &Self::Edge) -> Self::Node {
self.body[edge.source].terminator().successors().nth(edge.index).unwrap()
self.body()[edge.source].terminator().successors().nth(edge.index).unwrap()
}
}
struct BlockFormatter<'mir, 'tcx, A>
struct BlockFormatter<'a, 'mir, 'tcx, A>
where
A: Analysis<'tcx>,
{
results: ResultsCursor<'mir, 'tcx, A>,
cursor: &'a mut ResultsCursor<'mir, 'tcx, A>,
bg: Background,
style: OutputStyle,
}
impl<'mir, 'tcx, A> BlockFormatter<'mir, 'tcx, A>
impl<'tcx, A> BlockFormatter<'_, '_, 'tcx, A>
where
A: Analysis<'tcx>,
A::Domain: DebugWithContext<A>,
@ -173,7 +171,9 @@ where
bg
}
fn write_node_label(&mut self, w: &mut impl io::Write, block: BasicBlock) -> io::Result<()> {
fn write_node_label(&mut self, block: BasicBlock) -> io::Result<Vec<u8>> {
use std::io::Write;
// Sample output:
// +-+-----------------------------------------------+
// A | bb4 |
@ -200,6 +200,9 @@ where
// attributes. Make sure to test the output before trying to remove the redundancy.
// Notably, `align` was found to have no effect when applied only to <table>.
let mut v = vec![];
let w = &mut v;
let table_fmt = concat!(
" border=\"1\"",
" cellborder=\"1\"",
@ -219,8 +222,8 @@ where
// C: State at start of block
self.bg = Background::Light;
self.results.seek_to_block_start(block);
let block_start_state = self.results.get().clone();
self.cursor.seek_to_block_start(block);
let block_start_state = self.cursor.get().clone();
self.write_row_with_full_state(w, "", "(on start)")?;
// D + E: Statement and terminator transfer functions
@ -228,12 +231,12 @@ where
// F: State at end of block
let terminator = self.results.body()[block].terminator();
let terminator = self.cursor.body()[block].terminator();
// Write the full dataflow state immediately after the terminator if it differs from the
// state at block entry.
self.results.seek_to_block_end(block);
if self.results.get() != &block_start_state || A::Direction::IS_BACKWARD {
self.cursor.seek_to_block_end(block);
if self.cursor.get() != &block_start_state || A::Direction::IS_BACKWARD {
let after_terminator_name = match terminator.kind {
mir::TerminatorKind::Call { target: Some(_), .. } => "(on unwind)",
_ => "(on end)",
@ -250,8 +253,8 @@ where
match terminator.kind {
mir::TerminatorKind::Call { destination, .. } => {
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
let state_on_unwind = this.results.get().clone();
this.results.apply_custom_effect(|analysis, state| {
let state_on_unwind = this.cursor.get().clone();
this.cursor.apply_custom_effect(|analysis, state| {
analysis.apply_call_return_effect(
state,
block,
@ -265,9 +268,9 @@ where
colspan = this.style.num_state_columns(),
fmt = fmt,
diff = diff_pretty(
this.results.get(),
this.cursor.get(),
&state_on_unwind,
this.results.analysis()
this.cursor.analysis()
),
)
})?;
@ -275,8 +278,8 @@ where
mir::TerminatorKind::Yield { resume, resume_arg, .. } => {
self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
let state_on_coroutine_drop = this.results.get().clone();
this.results.apply_custom_effect(|analysis, state| {
let state_on_coroutine_drop = this.cursor.get().clone();
this.cursor.apply_custom_effect(|analysis, state| {
analysis.apply_call_return_effect(
state,
resume,
@ -290,9 +293,9 @@ where
colspan = this.style.num_state_columns(),
fmt = fmt,
diff = diff_pretty(
this.results.get(),
this.cursor.get(),
&state_on_coroutine_drop,
this.results.analysis()
this.cursor.analysis()
),
)
})?;
@ -302,8 +305,8 @@ where
if !targets.is_empty() =>
{
self.write_row(w, "", "(on successful return)", |this, w, fmt| {
let state_on_unwind = this.results.get().clone();
this.results.apply_custom_effect(|analysis, state| {
let state_on_unwind = this.cursor.get().clone();
this.cursor.apply_custom_effect(|analysis, state| {
analysis.apply_call_return_effect(
state,
block,
@ -317,9 +320,9 @@ where
colspan = this.style.num_state_columns(),
fmt = fmt,
diff = diff_pretty(
this.results.get(),
this.cursor.get(),
&state_on_unwind,
this.results.analysis()
this.cursor.analysis()
),
)
})?;
@ -328,7 +331,9 @@ where
_ => {}
};
write!(w, "</table>")
write!(w, "</table>")?;
Ok(v)
}
fn write_block_header_simple(
@ -407,9 +412,9 @@ where
block: BasicBlock,
) -> io::Result<()> {
let diffs = StateDiffCollector::run(
self.results.body(),
self.cursor.body(),
block,
self.results.mut_results(),
self.cursor.mut_results(),
self.style,
);
@ -420,7 +425,7 @@ where
if A::Direction::IS_FORWARD { it.next().unwrap() } else { it.next_back().unwrap() }
};
for (i, statement) in self.results.body()[block].statements.iter().enumerate() {
for (i, statement) in self.cursor.body()[block].statements.iter().enumerate() {
let statement_str = format!("{statement:?}");
let index_str = format!("{i}");
@ -442,7 +447,7 @@ where
assert!(diffs_after.is_empty());
assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty));
let terminator = self.results.body()[block].terminator();
let terminator = self.cursor.body()[block].terminator();
let mut terminator_str = String::new();
terminator.kind.fmt_head(&mut terminator_str).unwrap();
@ -492,8 +497,8 @@ where
mir: &str,
) -> io::Result<()> {
self.write_row(w, i, mir, |this, w, fmt| {
let state = this.results.get();
let analysis = this.results.analysis();
let state = this.cursor.get();
let analysis = this.cursor.analysis();
// FIXME: The full state vector can be quite long. It would be nice to split on commas
// and use some text wrapping algorithm.

View File

@ -84,7 +84,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
loop {
if libc::loadquery(
libc::L_GETINFO,
buffer.as_mut_ptr() as *mut i8,
buffer.as_mut_ptr() as *mut u8,
(std::mem::size_of::<libc::ld_info>() * buffer.len()) as u32,
) >= 0
{

View File

@ -198,10 +198,6 @@ fn generate_mergeable_doctest(
} else {
writeln!(output, "mod {test_id} {{\n{}{}", doctest.crates, doctest.maybe_crate_attrs)
.unwrap();
if scraped_test.langstr.no_run {
// To prevent having warnings about unused items since they're not called.
writeln!(output, "#![allow(unused)]").unwrap();
}
if doctest.has_main_fn {
output.push_str(&doctest.everything_else);
} else {

View File

@ -18,6 +18,7 @@ build_helper = { path = "../build_helper" }
tracing = "0.1"
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
regex = "1.0"
semver = { version = "1.0.23", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rustfix = "0.8.1"

View File

@ -7,6 +7,7 @@ use std::sync::OnceLock;
use std::{fmt, iter};
use build_helper::git::GitConfig;
use semver::Version;
use serde::de::{Deserialize, Deserializer, Error as _};
use test::{ColorConfig, OutputFormat};
@ -298,7 +299,7 @@ pub struct Config {
pub lldb_version: Option<u32>,
/// Version of LLVM
pub llvm_version: Option<u32>,
pub llvm_version: Option<Version>,
/// Is LLVM a system LLVM
pub system_llvm: bool,

View File

@ -6,6 +6,7 @@ use std::io::prelude::*;
use std::path::{Path, PathBuf};
use std::process::Command;
use semver::Version;
use tracing::*;
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
@ -1113,26 +1114,39 @@ fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
Some((regex, replacement))
}
pub fn extract_llvm_version(version: &str) -> Option<u32> {
let pat = |c: char| !c.is_ascii_digit() && c != '.';
let version_without_suffix = match version.find(pat) {
Some(pos) => &version[..pos],
/// Given an llvm version string that looks like `1.2.3-rc1`, extract as semver. Note that this
/// accepts more than just strict `semver` syntax (as in `major.minor.patch`); this permits omitting
/// minor and patch version components so users can write e.g. `//@ min-llvm-version: 19` instead of
/// having to write `//@ min-llvm-version: 19.0.0`.
///
/// Currently panics if the input string is malformed, though we really should not use panic as an
/// error handling strategy.
///
/// FIXME(jieyouxu): improve error handling
pub fn extract_llvm_version(version: &str) -> Version {
// The version substring we're interested in usually looks like the `1.2.3`, without any of the
// fancy suffix like `-rc1` or `meow`.
let version = version.trim();
let uninterested = |c: char| !c.is_ascii_digit() && c != '.';
let version_without_suffix = match version.split_once(uninterested) {
Some((prefix, _suffix)) => prefix,
None => version,
};
let components: Vec<u32> = version_without_suffix
let components: Vec<u64> = version_without_suffix
.split('.')
.map(|s| s.parse().expect("Malformed version component"))
.map(|s| s.parse().expect("llvm version component should consist of only digits"))
.collect();
let version = match *components {
[a] => a * 10_000,
[a, b] => a * 10_000 + b * 100,
[a, b, c] => a * 10_000 + b * 100 + c,
_ => panic!("Malformed version"),
};
Some(version)
match &components[..] {
[major] => Version::new(*major, 0, 0),
[major, minor] => Version::new(*major, *minor, 0),
[major, minor, patch] => Version::new(*major, *minor, *patch),
_ => panic!("malformed llvm version string, expected only 1-3 components: {version}"),
}
}
pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<Version> {
let output = Command::new(binary_path).arg("--version").output().ok()?;
if !output.status.success() {
return None;
@ -1140,7 +1154,7 @@ pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
let version = String::from_utf8(output.stdout).ok()?;
for line in version.lines() {
if let Some(version) = line.split("LLVM version ").nth(1) {
return extract_llvm_version(version);
return Some(extract_llvm_version(version));
}
}
None
@ -1247,15 +1261,17 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
false
}
/// Takes a directive of the form `"<version1> [- <version2>]"`,
/// returns the numeric representation of `<version1>` and `<version2>` as
/// tuple: `(<version1> as u32, <version2> as u32)`.
/// Takes a directive of the form `"<version1> [- <version2>]"`, returns the numeric representation
/// of `<version1>` and `<version2>` as tuple: `(<version1>, <version2>)`.
///
/// If the `<version2>` part is omitted, the second component of the tuple
/// is the same as `<version1>`.
fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
/// If the `<version2>` part is omitted, the second component of the tuple is the same as
/// `<version1>`.
fn extract_version_range<'a, F, VersionTy: Clone>(
line: &'a str,
parse: F,
) -> Option<(VersionTy, VersionTy)>
where
F: Fn(&str) -> Option<u32>,
F: Fn(&'a str) -> Option<VersionTy>,
{
let mut splits = line.splitn(2, "- ").map(str::trim);
let min = splits.next().unwrap();
@ -1273,7 +1289,7 @@ where
let max = match max {
Some("") => return None,
Some(max) => parse(max)?,
_ => min,
_ => min.clone(),
};
Some((min, max))
@ -1489,43 +1505,55 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
};
}
}
if let Some(actual_version) = config.llvm_version {
if let Some(rest) = line.strip_prefix("min-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
// Ignore if actual version is smaller the minimum required
// version
if actual_version < min_version {
if let Some(actual_version) = &config.llvm_version {
// Note that these `min` versions will check for not just major versions.
if let Some(version_string) = config.parse_name_value_directive(line, "min-llvm-version") {
let min_version = extract_llvm_version(&version_string);
// Ignore if actual version is smaller than the minimum required version.
if *actual_version < min_version {
return IgnoreDecision::Ignore {
reason: format!("ignored when the LLVM version is older than {rest}"),
reason: format!(
"ignored when the LLVM version {actual_version} is older than {min_version}"
),
};
}
} else if let Some(rest) = line.strip_prefix("min-system-llvm-version:").map(str::trim) {
let min_version = extract_llvm_version(rest).unwrap();
} else if let Some(version_string) =
config.parse_name_value_directive(line, "min-system-llvm-version")
{
let min_version = extract_llvm_version(&version_string);
// Ignore if using system LLVM and actual version
// is smaller the minimum required version
if config.system_llvm && actual_version < min_version {
if config.system_llvm && *actual_version < min_version {
return IgnoreDecision::Ignore {
reason: format!("ignored when the system LLVM version is older than {rest}"),
reason: format!(
"ignored when the system LLVM version {actual_version} is older than {min_version}"
),
};
}
} else if let Some(rest) = line.strip_prefix("ignore-llvm-version:").map(str::trim) {
} else if let Some(version_range) =
config.parse_name_value_directive(line, "ignore-llvm-version")
{
// Syntax is: "ignore-llvm-version: <version1> [- <version2>]"
let (v_min, v_max) =
extract_version_range(rest, extract_llvm_version).unwrap_or_else(|| {
panic!("couldn't parse version range: {:?}", rest);
});
extract_version_range(&version_range, |s| Some(extract_llvm_version(s)))
.unwrap_or_else(|| {
panic!("couldn't parse version range: \"{version_range}\"");
});
if v_max < v_min {
panic!("Malformed LLVM version range: max < min")
panic!("malformed LLVM version range where {v_max} < {v_min}")
}
// Ignore if version lies inside of range.
if actual_version >= v_min && actual_version <= v_max {
if *actual_version >= v_min && *actual_version <= v_max {
if v_min == v_max {
return IgnoreDecision::Ignore {
reason: format!("ignored when the LLVM version is {rest}"),
reason: format!("ignored when the LLVM version is {actual_version}"),
};
} else {
return IgnoreDecision::Ignore {
reason: format!("ignored when the LLVM version is between {rest}"),
reason: format!(
"ignored when the LLVM version is between {v_min} and {v_max}"
),
};
}
}

View File

@ -1,9 +1,13 @@
use std::io::Read;
use std::path::Path;
use super::iter_header;
use semver::Version;
use super::{
EarlyProps, HeadersCache, extract_llvm_version, extract_version_range, iter_header,
parse_normalize_rule,
};
use crate::common::{Config, Debugger, Mode};
use crate::header::{EarlyProps, HeadersCache, parse_normalize_rule};
fn make_test_description<R: Read>(
config: &Config,
@ -408,18 +412,66 @@ fn channel() {
}
#[test]
fn test_extract_version_range() {
use super::{extract_llvm_version, extract_version_range};
fn test_extract_llvm_version() {
// Note: officially, semver *requires* that versions at the minimum have all three
// `major.minor.patch` numbers, though for test-writer's convenience we allow omitting the minor
// and patch numbers (which will be stubbed out as 0).
assert_eq!(extract_llvm_version("0"), Version::new(0, 0, 0));
assert_eq!(extract_llvm_version("0.0"), Version::new(0, 0, 0));
assert_eq!(extract_llvm_version("0.0.0"), Version::new(0, 0, 0));
assert_eq!(extract_llvm_version("1"), Version::new(1, 0, 0));
assert_eq!(extract_llvm_version("1.2"), Version::new(1, 2, 0));
assert_eq!(extract_llvm_version("1.2.3"), Version::new(1, 2, 3));
assert_eq!(extract_llvm_version("4.5.6git"), Version::new(4, 5, 6));
assert_eq!(extract_llvm_version("4.5.6-rc1"), Version::new(4, 5, 6));
assert_eq!(extract_llvm_version("123.456.789-rc1"), Version::new(123, 456, 789));
assert_eq!(extract_llvm_version("8.1.2-rust"), Version::new(8, 1, 2));
assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Version::new(9, 0, 1));
assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Version::new(9, 3, 1));
assert_eq!(extract_llvm_version("10.0.0-rust"), Version::new(10, 0, 0));
assert_eq!(extract_llvm_version("11.1.0"), Version::new(11, 1, 0));
assert_eq!(extract_llvm_version("12.0.0libcxx"), Version::new(12, 0, 0));
assert_eq!(extract_llvm_version("12.0.0-rc3"), Version::new(12, 0, 0));
assert_eq!(extract_llvm_version("13.0.0git"), Version::new(13, 0, 0));
}
assert_eq!(extract_version_range("1.2.3 - 4.5.6", extract_llvm_version), Some((10203, 40506)));
assert_eq!(extract_version_range("0 - 4.5.6", extract_llvm_version), Some((0, 40506)));
assert_eq!(extract_version_range("1.2.3 -", extract_llvm_version), None);
assert_eq!(extract_version_range("1.2.3 - ", extract_llvm_version), None);
assert_eq!(extract_version_range("- 4.5.6", extract_llvm_version), None);
assert_eq!(extract_version_range("-", extract_llvm_version), None);
assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
assert_eq!(extract_version_range(" - 4.5.6", extract_llvm_version), None);
assert_eq!(extract_version_range("0 -", extract_llvm_version), None);
#[test]
#[should_panic]
fn test_llvm_version_invalid_components() {
extract_llvm_version("4.x.6");
}
#[test]
#[should_panic]
fn test_llvm_version_invalid_prefix() {
extract_llvm_version("meow4.5.6");
}
#[test]
#[should_panic]
fn test_llvm_version_too_many_components() {
extract_llvm_version("4.5.6.7");
}
#[test]
fn test_extract_version_range() {
let wrapped_extract = |s: &str| Some(extract_llvm_version(s));
assert_eq!(
extract_version_range("1.2.3 - 4.5.6", wrapped_extract),
Some((Version::new(1, 2, 3), Version::new(4, 5, 6)))
);
assert_eq!(
extract_version_range("0 - 4.5.6", wrapped_extract),
Some((Version::new(0, 0, 0), Version::new(4, 5, 6)))
);
assert_eq!(extract_version_range("1.2.3 -", wrapped_extract), None);
assert_eq!(extract_version_range("1.2.3 - ", wrapped_extract), None);
assert_eq!(extract_version_range("- 4.5.6", wrapped_extract), None);
assert_eq!(extract_version_range("-", wrapped_extract), None);
assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
assert_eq!(extract_version_range(" - 4.5.6", wrapped_extract), None);
assert_eq!(extract_version_range("0 -", wrapped_extract), None);
}
#[test]

View File

@ -228,7 +228,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
};
let llvm_version =
matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
matches.opt_str("llvm-version").as_deref().map(header::extract_llvm_version).or_else(
|| header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
);

View File

@ -1,7 +1,6 @@
use std::ffi::OsString;
use crate::debuggers::{extract_gdb_version, extract_lldb_version};
use crate::header::extract_llvm_version;
use crate::is_test;
#[test]
@ -67,15 +66,3 @@ fn is_test_test() {
assert!(!is_test(&OsString::from("#a_dog_gif")));
assert!(!is_test(&OsString::from("~a_temp_file")));
}
#[test]
fn test_extract_llvm_version() {
assert_eq!(extract_llvm_version("8.1.2-rust"), Some(80102));
assert_eq!(extract_llvm_version("9.0.1-rust-1.43.0-dev"), Some(90001));
assert_eq!(extract_llvm_version("9.3.1-rust-1.43.0-dev"), Some(90301));
assert_eq!(extract_llvm_version("10.0.0-rust"), Some(100000));
assert_eq!(extract_llvm_version("11.1.0"), Some(110100));
assert_eq!(extract_llvm_version("12.0.0libcxx"), Some(120000));
assert_eq!(extract_llvm_version("12.0.0-rc3"), Some(120000));
assert_eq!(extract_llvm_version("13.0.0git"), Some(130000));
}

View File

@ -4102,7 +4102,6 @@ ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
ui/type-alias-impl-trait/issue-57188-associate-impl-capture.rs
ui/type-alias-impl-trait/issue-57611-trait-alias.rs
ui/type-alias-impl-trait/issue-57700.rs
ui/type-alias-impl-trait/issue-57807-associated-type.rs
ui/type-alias-impl-trait/issue-57961.rs
ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs

View File

@ -0,0 +1,15 @@
// This test ensures that the 2024 edition merged doctest will not use `#[allow(unused)]`.
//@ compile-flags:--test -Zunstable-options --edition 2024
//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
//@ failure-status: 101
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
/// Example
///
/// ```rust,no_run
/// trait T { fn f(); }
/// ```
pub fn f() {}

View File

@ -0,0 +1,29 @@
running 1 test
test $DIR/dead-code-2024.rs - f (line 12) - compile ... FAILED
failures:
---- $DIR/dead-code-2024.rs - f (line 12) stdout ----
error: trait `T` is never used
--> $DIR/dead-code-2024.rs:13:7
|
LL | trait T { fn f(); }
| ^
|
note: the lint level is defined here
--> $DIR/dead-code-2024.rs:11:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
error: aborting due to 1 previous error
Couldn't compile the test.
failures:
$DIR/dead-code-2024.rs - f (line 12)
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

View File

@ -0,0 +1,15 @@
// This test ensures that the doctest will not use `#[allow(unused)]`.
//@ compile-flags:--test
//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
//@ failure-status: 101
#![doc(test(attr(allow(unused_variables), deny(warnings))))]
/// Example
///
/// ```rust,no_run
/// trait T { fn f(); }
/// ```
pub fn f() {}

View File

@ -0,0 +1,29 @@
running 1 test
test $DIR/dead-code.rs - f (line 12) - compile ... FAILED
failures:
---- $DIR/dead-code.rs - f (line 12) stdout ----
error: trait `T` is never used
--> $DIR/dead-code.rs:13:7
|
LL | trait T { fn f(); }
| ^
|
note: the lint level is defined here
--> $DIR/dead-code.rs:11:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(dead_code)]` implied by `#[deny(warnings)]`
error: aborting due to 1 previous error
Couldn't compile the test.
failures:
$DIR/dead-code.rs - f (line 12)
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME

View File

@ -8,7 +8,7 @@ use std::ops::Deref;
struct Foo(u32);
impl Foo {
const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
//~^ ERROR: `R` cannot be used as the type of `self`
//~^ ERROR invalid generic `self` parameter type
//~| ERROR destructor of `R` cannot be evaluated at compile-time
self.0
//~^ ERROR cannot call non-const fn `<R as Deref>::deref` in constant function

View File

@ -15,18 +15,16 @@ LL | const fn get<R: Deref<Target = Self>>(self: R) -> u32 {
LL | }
| - value is dropped here
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
error[E0801]: invalid generic `self` parameter type: `R`
--> $DIR/arbitrary-self-from-method-substs-ice.rs:10:49
|
LL | const 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= 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`)
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493, E0658.
Some errors have detailed explanations: E0015, E0493, E0801.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,14 +1,168 @@
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
error[E0801]: invalid generic `self` parameter type: `R`
--> $DIR/arbitrary-self-from-method-substs.rs:9:43
|
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
| ^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `&R`
--> $DIR/arbitrary-self-from-method-substs.rs:13:44
|
LL | fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
| ^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `&mut R`
--> $DIR/arbitrary-self-from-method-substs.rs:17:44
|
LL | fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
| ^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `Rc<R>`
--> $DIR/arbitrary-self-from-method-substs.rs:21:44
|
LL | fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
| ^^^^^^^^^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `&Rc<R>`
--> $DIR/arbitrary-self-from-method-substs.rs:25:44
|
LL | fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
| ^^^^^^^^^^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `Rc<&R>`
--> $DIR/arbitrary-self-from-method-substs.rs:29:44
|
LL | fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
| ^^^^^^^^^^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0658]: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self` without the `arbitrary_self_types` feature
--> $DIR/arbitrary-self-from-method-substs.rs:33:37
|
LL | fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= 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 1 previous error
error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature
--> $DIR/arbitrary-self-from-method-substs.rs:61:18
|
LL | fn get(self: R) {}
| ^
|
= 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
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= 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`)
For more information about this error, try `rustc --explain E0658`.
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:92:9
|
LL | foo.get6(Silly);
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
|
note: expected this to be `Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
LL | type Receiver = std::rc::Rc<Foo>;
| ^^^^^^^^^^^^^^^^
= note: expected struct `Foo`
found struct `Rc<Foo>`
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:96:9
|
LL | foo.get6(Silly);
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
|
note: expected this to be `&Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
LL | type Receiver = std::rc::Rc<Foo>;
| ^^^^^^^^^^^^^^^^
= note: expected reference `&Foo`
found struct `Rc<Foo>`
error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
--> $DIR/arbitrary-self-from-method-substs.rs:100:7
|
LL | struct Bar<R>(std::marker::PhantomData<R>);
| ------------- doesn't satisfy `Bar<_>: Deref`
...
LL | t.get();
| ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
`Bar<_>: Deref`
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
note: the trait `Deref` must be implemented
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `get`, perhaps you need to implement it:
candidate #1: `SliceIndex`
error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
--> $DIR/arbitrary-self-from-method-substs.rs:108:7
|
LL | struct Bar<R>(std::marker::PhantomData<R>);
| ------------- doesn't satisfy `Bar<_>: Deref`
...
LL | t.get();
| ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
`<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
`Bar<_>: Deref`
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
note: the trait `Deref` must be implemented
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `get`, perhaps you need to implement it:
candidate #1: `SliceIndex`
error: aborting due to 12 previous errors
Some errors have detailed explanations: E0271, E0599, E0658, E0801.
For more information about an error, try `rustc --explain E0271`.

View File

@ -1,9 +1,179 @@
error[E0801]: invalid generic `self` parameter type: `R`
--> $DIR/arbitrary-self-from-method-substs.rs:9:43
|
LL | fn get<R: Deref<Target = Self>>(self: R) -> u32 {
| ^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `&R`
--> $DIR/arbitrary-self-from-method-substs.rs:13:44
|
LL | fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
| ^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `&mut R`
--> $DIR/arbitrary-self-from-method-substs.rs:17:44
|
LL | fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
| ^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `Rc<R>`
--> $DIR/arbitrary-self-from-method-substs.rs:21:44
|
LL | fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
| ^^^^^^^^^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `&Rc<R>`
--> $DIR/arbitrary-self-from-method-substs.rs:25:44
|
LL | fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
| ^^^^^^^^^^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0801]: invalid generic `self` parameter type: `Rc<&R>`
--> $DIR/arbitrary-self-from-method-substs.rs:29:44
|
LL | fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
| ^^^^^^^^^^^^^^^
|
= note: type of `self` must not be a method generic parameter type
= help: 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`)
error[E0308]: mismatched types
--> $DIR/arbitrary-self-from-method-substs.rs:16:5
--> $DIR/arbitrary-self-from-method-substs.rs:76:5
|
LL | foo.get::<&Foo>();
| ^^^ expected `&Foo`, found `Foo`
error: aborting due to 1 previous error
error[E0308]: mismatched types
--> $DIR/arbitrary-self-from-method-substs.rs:78:5
|
LL | foo.get::<std::rc::Rc<Foo>>();
| ^^^ expected `Rc<Foo>`, found `Foo`
|
= note: expected struct `Rc<Foo>`
found struct `Foo`
For more information about this error, try `rustc --explain E0308`.
error[E0308]: mismatched types
--> $DIR/arbitrary-self-from-method-substs.rs:84:5
|
LL | smart_ptr.get::<SmartPtr2<Foo>>();
| ^^^^^^^^^ expected `SmartPtr2<'_, Foo>`, found `SmartPtr<'_, Foo>`
|
= note: expected struct `SmartPtr2<'_, Foo>`
found struct `SmartPtr<'_, Foo>`
error[E0308]: mismatched types
--> $DIR/arbitrary-self-from-method-substs.rs:86:5
|
LL | smart_ptr.get::<&Foo>();
| ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>`
|
= note: expected reference `&Foo`
found struct `SmartPtr<'_, Foo, >`
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:92:9
|
LL | foo.get6(Silly);
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo`
|
note: expected this to be `Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
LL | type Receiver = std::rc::Rc<Foo>;
| ^^^^^^^^^^^^^^^^
= note: expected struct `Foo`
found struct `Rc<Foo>`
error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:96:9
|
LL | foo.get6(Silly);
| ^^^^ type mismatch resolving `<Silly as FindReceiver>::Receiver == &Foo`
|
note: expected this to be `&Foo`
--> $DIR/arbitrary-self-from-method-substs.rs:71:21
|
LL | type Receiver = std::rc::Rc<Foo>;
| ^^^^^^^^^^^^^^^^
= note: expected reference `&Foo`
found struct `Rc<Foo>`
error[E0599]: the method `get` exists for struct `Rc<Bar<_>>`, but its trait bounds were not satisfied
--> $DIR/arbitrary-self-from-method-substs.rs:100:7
|
LL | struct Bar<R>(std::marker::PhantomData<R>);
| ------------- doesn't satisfy `Bar<_>: Deref`
...
LL | t.get();
| ^^^ method cannot be called on `Rc<Bar<_>>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
`Bar<_>: Deref`
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
note: the trait `Deref` must be implemented
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `get`, perhaps you need to implement it:
candidate #1: `SliceIndex`
error[E0599]: the method `get` exists for reference `&Rc<Bar<_>>`, but its trait bounds were not satisfied
--> $DIR/arbitrary-self-from-method-substs.rs:108:7
|
LL | struct Bar<R>(std::marker::PhantomData<R>);
| ------------- doesn't satisfy `Bar<_>: Deref`
...
LL | t.get();
| ^^^ method cannot be called on `&Rc<Bar<_>>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
`<&&Rc<Bar<_>> as Deref>::Target = Bar<&&Rc<Bar<_>>>`
`<&Bar<_> as Deref>::Target = Bar<&Bar<_>>`
`<&Rc<Bar<_>> as Deref>::Target = Bar<&Rc<Bar<_>>>`
`<&mut &Rc<Bar<_>> as Deref>::Target = Bar<&mut &Rc<Bar<_>>>`
`<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>`
`<&mut Rc<Bar<_>> as Deref>::Target = Bar<&mut Rc<Bar<_>>>`
`<Rc<Bar<_>> as Deref>::Target = Bar<Rc<Bar<_>>>`
`Bar<_>: Deref`
--> $DIR/arbitrary-self-from-method-substs.rs:60:9
|
LL | impl<R: std::ops::Deref<Target = Self>> Bar<R> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------
| | |
| | unsatisfied trait bound introduced here
| unsatisfied trait bound introduced here
note: the trait `Deref` must be implemented
--> $SRC_DIR/core/src/ops/deref.rs:LL:COL
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `get`, perhaps you need to implement it:
candidate #1: `SliceIndex`
error: aborting due to 14 previous errors
Some errors have detailed explanations: E0271, E0308, E0599, E0801.
For more information about an error, try `rustc --explain E0271`.

View File

@ -2,17 +2,109 @@
#![cfg_attr(feature, feature(arbitrary_self_types))]
use std::ops::Deref;
use std::marker::PhantomData;
struct Foo(u32);
impl Foo {
fn get<R: Deref<Target = Self>>(self: R) -> u32 {
//[default]~^ ERROR: `R` cannot be used as the type of `self`
//~^ ERROR: invalid generic `self` parameter type
self.0
}
fn get1<R: Deref<Target = Self>>(self: &R) -> u32 {
//~^ ERROR: invalid generic `self` parameter type
self.0
}
fn get2<R: Deref<Target = Self>>(self: &mut R) -> u32 {
//~^ ERROR: invalid generic `self` parameter type
self.0
}
fn get3<R: Deref<Target = Self>>(self: std::rc::Rc<R>) -> u32 {
//~^ ERROR: invalid generic `self` parameter type
self.0
}
fn get4<R: Deref<Target = Self>>(self: &std::rc::Rc<R>) -> u32 {
//~^ ERROR: invalid generic `self` parameter type
self.0
}
fn get5<R: Deref<Target = Self>>(self: std::rc::Rc<&R>) -> u32 {
//~^ ERROR: invalid generic `self` parameter type
self.0
}
fn get6<FR: FindReceiver>(self: FR::Receiver, other: FR) -> u32 {
//[default]~^ ERROR: `<FR as FindReceiver>::Receiver` cannot be used as the type of `self`
42
}
}
struct SmartPtr<'a, T: ?Sized>(&'a T);
impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unimplemented!()
}
}
struct SmartPtr2<'a, T: ?Sized>(&'a T);
impl<'a, T: ?Sized> Deref for SmartPtr2<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unimplemented!()
}
}
struct Bar<R>(std::marker::PhantomData<R>);
impl<R: std::ops::Deref<Target = Self>> Bar<R> {
fn get(self: R) {}
//[default]~^ ERROR: `R` cannot be used as the type of `self`
}
trait FindReceiver {
type Receiver: Deref<Target = Foo>;
}
struct Silly;
impl FindReceiver for Silly {
type Receiver = std::rc::Rc<Foo>;
}
fn main() {
let mut foo = Foo(1);
foo.get::<&Foo>();
//[feature]~^ ERROR mismatched types
foo.get::<std::rc::Rc<Foo>>();
//[feature]~^ ERROR mismatched types
let smart_ptr = SmartPtr(&foo);
let smart_ptr2 = SmartPtr2(&foo);
smart_ptr.get(); // this compiles
smart_ptr.get::<SmartPtr2<Foo>>();
//[feature]~^ ERROR mismatched types
smart_ptr.get::<&Foo>();
//[feature]~^ ERROR mismatched types
let mut foo = Foo(1);
// This test is slightly contrived in an attempt to generate a mismatched types
// error for the self type below, without using the turbofish.
foo.get6(Silly);
//~^ ERROR type mismatch
let mut foo = Foo(1);
let foo = &foo;
foo.get6(Silly);
//~^ ERROR type mismatch
let t = std::rc::Rc::new(Bar(std::marker::PhantomData));
t.get();
//~^ ERROR its trait bounds were not satisfied
let t = &t;
// This is a further attempt at triggering 'type mismatch' errors
// from arbitrary self types without resorting to the turbofish.
// Ideally, here, t is Thing<Rc<Target=Self>> while we're going to call
// it with a &t method receiver. However, this doesn't work since that
// type of t becomes recursive and trait bounds can't be satisfied.
t.get();
//~^ ERROR its trait bounds were not satisfied
}

View File

@ -1,21 +0,0 @@
#![feature(arbitrary_self_types)]
#![feature(impl_trait_in_assoc_type)]
use std::ops::Deref;
trait Foo {
type Bar: Foo;
fn foo(self: impl Deref<Target = Self>) -> Self::Bar;
}
impl<C> Foo for C {
type Bar = impl Foo;
fn foo(self: impl Deref<Target = Self>) -> Self::Bar {
self
//~^ Error type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
}
}
fn main() {}

View File

@ -1,8 +0,0 @@
error: type parameter `impl Deref<Target = Self>` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> $DIR/issue-57700.rs:16:9
|
LL | self
| ^^^^
error: aborting due to 1 previous error

View File

@ -966,7 +966,6 @@ cc = ["@kobzol"]
warn_non_default_branch = true
contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [
"BoxyUwU",
"fmease",
"jyn514",
"oli-obk",