Auto merge of #146650 - matthiaskrgr:rollup-rjrklz9, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - rust-lang/rust#146442 (Display ?Sized, const, and lifetime parameters in trait item suggestions across a crate boundary) - rust-lang/rust#146474 (Improve `core::ascii` coverage) - rust-lang/rust#146605 (Bump rustfix 0.8.1 -> 0.8.7) - rust-lang/rust#146611 (bootstrap: emit hint if a config key is used in the wrong section) - rust-lang/rust#146618 (Do not run ui test if options specific to LLVM are used when another codegen backend is used) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
3f1552a273
15 changed files with 183 additions and 43 deletions
|
|
@ -4817,9 +4817,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustfix"
|
name = "rustfix"
|
||||||
version = "0.8.1"
|
version = "0.8.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4"
|
checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ pub mod intrinsic;
|
||||||
mod region;
|
mod region;
|
||||||
pub mod wfcheck;
|
pub mod wfcheck;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
|
||||||
pub use check::{check_abi, check_custom_abi};
|
pub use check::{check_abi, check_custom_abi};
|
||||||
|
|
@ -86,7 +87,7 @@ use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::print::with_types_for_signature;
|
use rustc_middle::ty::print::with_types_for_signature;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TyCtxt, TypingMode,
|
self, GenericArgs, GenericArgsRef, OutlivesPredicate, Region, Ty, TyCtxt, TypingMode,
|
||||||
};
|
};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
|
|
@ -335,6 +336,7 @@ fn bounds_from_generic_predicates<'tcx>(
|
||||||
assoc: ty::AssocItem,
|
assoc: ty::AssocItem,
|
||||||
) -> (String, String) {
|
) -> (String, String) {
|
||||||
let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
|
let mut types: FxIndexMap<Ty<'tcx>, Vec<DefId>> = FxIndexMap::default();
|
||||||
|
let mut regions: FxIndexMap<Region<'tcx>, Vec<Region<'tcx>>> = FxIndexMap::default();
|
||||||
let mut projections = vec![];
|
let mut projections = vec![];
|
||||||
for (predicate, _) in predicates {
|
for (predicate, _) in predicates {
|
||||||
debug!("predicate {:?}", predicate);
|
debug!("predicate {:?}", predicate);
|
||||||
|
|
@ -351,20 +353,23 @@ fn bounds_from_generic_predicates<'tcx>(
|
||||||
ty::ClauseKind::Projection(projection_pred) => {
|
ty::ClauseKind::Projection(projection_pred) => {
|
||||||
projections.push(bound_predicate.rebind(projection_pred));
|
projections.push(bound_predicate.rebind(projection_pred));
|
||||||
}
|
}
|
||||||
|
ty::ClauseKind::RegionOutlives(OutlivesPredicate(a, b)) => {
|
||||||
|
regions.entry(a).or_default().push(b);
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut where_clauses = vec![];
|
let mut where_clauses = vec![];
|
||||||
let generics = tcx.generics_of(assoc.def_id);
|
let generics = tcx.generics_of(assoc.def_id);
|
||||||
let types_str = generics
|
let params = generics
|
||||||
.own_params
|
.own_params
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|p| matches!(p.kind, GenericParamDefKind::Type { synthetic: false, .. }))
|
.filter(|p| !p.kind.is_synthetic())
|
||||||
.map(|p| {
|
.map(|p| match tcx.mk_param_from_def(p).kind() {
|
||||||
// we just checked that it's a type, so the unwrap can't fail
|
ty::GenericArgKind::Type(ty) => {
|
||||||
let ty = tcx.mk_param_from_def(p).as_type().unwrap();
|
let bounds =
|
||||||
if let Some(bounds) = types.get(&ty) {
|
types.get(&ty).map(Cow::Borrowed).unwrap_or_else(|| Cow::Owned(Vec::new()));
|
||||||
let mut bounds_str = vec![];
|
let mut bounds_str = vec![];
|
||||||
for bound in bounds.iter().copied() {
|
for bound in bounds.iter().copied() {
|
||||||
let mut projections_str = vec![];
|
let mut projections_str = vec![];
|
||||||
|
|
@ -377,7 +382,11 @@ fn bounds_from_generic_predicates<'tcx>(
|
||||||
projections_str.push(format!("{} = {}", name, p.term));
|
projections_str.push(format!("{} = {}", name, p.term));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let bound_def_path = tcx.def_path_str(bound);
|
let bound_def_path = if tcx.is_lang_item(bound, LangItem::MetaSized) {
|
||||||
|
String::from("?Sized")
|
||||||
|
} else {
|
||||||
|
tcx.def_path_str(bound)
|
||||||
|
};
|
||||||
if projections_str.is_empty() {
|
if projections_str.is_empty() {
|
||||||
where_clauses.push(format!("{}: {}", ty, bound_def_path));
|
where_clauses.push(format!("{}: {}", ty, bound_def_path));
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -393,8 +402,21 @@ fn bounds_from_generic_predicates<'tcx>(
|
||||||
} else {
|
} else {
|
||||||
format!("{}: {}", ty, bounds_str.join(" + "))
|
format!("{}: {}", ty, bounds_str.join(" + "))
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
ty.to_string()
|
ty::GenericArgKind::Const(ct) => {
|
||||||
|
format!("const {ct}: {}", tcx.type_of(p.def_id).skip_binder())
|
||||||
|
}
|
||||||
|
ty::GenericArgKind::Lifetime(region) => {
|
||||||
|
if let Some(v) = regions.get(®ion)
|
||||||
|
&& !v.is_empty()
|
||||||
|
{
|
||||||
|
format!(
|
||||||
|
"{region}: {}",
|
||||||
|
v.into_iter().map(Region::to_string).collect::<Vec<_>>().join(" + ")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
region.to_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
@ -409,7 +431,7 @@ fn bounds_from_generic_predicates<'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let generics =
|
let generics =
|
||||||
if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
|
if params.is_empty() { "".to_string() } else { format!("<{}>", params.join(", ")) };
|
||||||
|
|
||||||
let where_clauses = if where_clauses.is_empty() {
|
let where_clauses = if where_clauses.is_empty() {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
|
|
|
||||||
|
|
@ -505,3 +505,10 @@ fn test_escape_ascii_iter() {
|
||||||
let _ = it.advance_back_by(4);
|
let _ = it.advance_back_by(4);
|
||||||
assert_eq!(it.to_string(), r#"fastpath\xffremainder"#);
|
assert_eq!(it.to_string(), r#"fastpath\xffremainder"#);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_invalid_u8() {
|
||||||
|
for c in 128..=255 {
|
||||||
|
assert_eq!(core::ascii::Char::from_u8(c), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1853,13 +1853,7 @@ fn load_toml_config(
|
||||||
} else {
|
} else {
|
||||||
toml_path.clone()
|
toml_path.clone()
|
||||||
});
|
});
|
||||||
(
|
(get_toml(&toml_path).unwrap_or_else(|e| bad_config(&toml_path, e)), path)
|
||||||
get_toml(&toml_path).unwrap_or_else(|e| {
|
|
||||||
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
|
|
||||||
exit!(2);
|
|
||||||
}),
|
|
||||||
path,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(TomlConfig::default(), None)
|
(TomlConfig::default(), None)
|
||||||
}
|
}
|
||||||
|
|
@ -1892,10 +1886,8 @@ fn postprocess_toml(
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join(include_path);
|
.join(include_path);
|
||||||
|
|
||||||
let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
|
let included_toml =
|
||||||
eprintln!("ERROR: Failed to parse '{}': {e}", include_path.display());
|
get_toml(&include_path).unwrap_or_else(|e| bad_config(&include_path, e));
|
||||||
exit!(2);
|
|
||||||
});
|
|
||||||
toml.merge(
|
toml.merge(
|
||||||
Some(include_path),
|
Some(include_path),
|
||||||
&mut Default::default(),
|
&mut Default::default(),
|
||||||
|
|
@ -2398,3 +2390,98 @@ pub(crate) fn read_file_by_commit<'a>(
|
||||||
git.arg("show").arg(format!("{commit}:{}", file.to_str().unwrap()));
|
git.arg("show").arg(format!("{commit}:{}", file.to_str().unwrap()));
|
||||||
git.run_capture_stdout(dwn_ctx.exec_ctx).stdout()
|
git.run_capture_stdout(dwn_ctx.exec_ctx).stdout()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bad_config(toml_path: &Path, e: toml::de::Error) -> ! {
|
||||||
|
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
|
||||||
|
let e_s = e.to_string();
|
||||||
|
if e_s.contains("unknown field")
|
||||||
|
&& let Some(field_name) = e_s.split("`").nth(1)
|
||||||
|
&& let sections = find_correct_section_for_field(field_name)
|
||||||
|
&& !sections.is_empty()
|
||||||
|
{
|
||||||
|
if sections.len() == 1 {
|
||||||
|
match sections[0] {
|
||||||
|
WouldBeValidFor::TopLevel { is_section } => {
|
||||||
|
if is_section {
|
||||||
|
eprintln!(
|
||||||
|
"hint: section name `{field_name}` used as a key within a section"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
eprintln!("hint: try using `{field_name}` as a top level key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WouldBeValidFor::Section(section) => {
|
||||||
|
eprintln!("hint: try moving `{field_name}` to the `{section}` section")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"hint: `{field_name}` would be valid {}",
|
||||||
|
join_oxford_comma(sections.iter(), "or"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit!(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
enum WouldBeValidFor {
|
||||||
|
TopLevel { is_section: bool },
|
||||||
|
Section(&'static str),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn join_oxford_comma(
|
||||||
|
mut parts: impl ExactSizeIterator<Item = impl std::fmt::Display>,
|
||||||
|
conj: &str,
|
||||||
|
) -> String {
|
||||||
|
use std::fmt::Write;
|
||||||
|
let mut out = String::new();
|
||||||
|
|
||||||
|
assert!(parts.len() > 1);
|
||||||
|
while let Some(part) = parts.next() {
|
||||||
|
if parts.len() == 0 {
|
||||||
|
write!(&mut out, "{conj} {part}")
|
||||||
|
} else {
|
||||||
|
write!(&mut out, "{part}, ")
|
||||||
|
}
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for WouldBeValidFor {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::TopLevel { .. } => write!(f, "at top level"),
|
||||||
|
Self::Section(section_name) => write!(f, "in section `{section_name}`"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_correct_section_for_field(field_name: &str) -> Vec<WouldBeValidFor> {
|
||||||
|
let sections = ["build", "install", "llvm", "gcc", "rust", "dist"];
|
||||||
|
sections
|
||||||
|
.iter()
|
||||||
|
.map(Some)
|
||||||
|
.chain([None])
|
||||||
|
.filter_map(|section_name| {
|
||||||
|
let dummy_config_str = if let Some(section_name) = section_name {
|
||||||
|
format!("{section_name}.{field_name} = 0\n")
|
||||||
|
} else {
|
||||||
|
format!("{field_name} = 0\n")
|
||||||
|
};
|
||||||
|
let is_unknown_field = toml::from_str::<toml::Value>(&dummy_config_str)
|
||||||
|
.and_then(TomlConfig::deserialize)
|
||||||
|
.err()
|
||||||
|
.is_some_and(|e| e.to_string().contains("unknown field"));
|
||||||
|
if is_unknown_field {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(section_name.copied().map(WouldBeValidFor::Section).unwrap_or_else(|| {
|
||||||
|
WouldBeValidFor::TopLevel { is_section: sections.contains(&field_name) }
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,10 @@ impl CodegenBackend {
|
||||||
Self::Llvm => "llvm",
|
Self::Llvm => "llvm",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_llvm(self) -> bool {
|
||||||
|
matches!(self, Self::Llvm)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configuration for `compiletest` *per invocation*.
|
/// Configuration for `compiletest` *per invocation*.
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,8 @@ pub(super) fn handle_needs(
|
||||||
},
|
},
|
||||||
Need {
|
Need {
|
||||||
name: "needs-enzyme",
|
name: "needs-enzyme",
|
||||||
condition: config.has_enzyme,
|
condition: config.has_enzyme && config.default_codegen_backend.is_llvm(),
|
||||||
ignore_reason: "ignored when LLVM Enzyme is disabled",
|
ignore_reason: "ignored when LLVM Enzyme is disabled or LLVM is not the default codegen backend",
|
||||||
},
|
},
|
||||||
Need {
|
Need {
|
||||||
name: "needs-run-enabled",
|
name: "needs-run-enabled",
|
||||||
|
|
@ -161,8 +161,8 @@ pub(super) fn handle_needs(
|
||||||
},
|
},
|
||||||
Need {
|
Need {
|
||||||
name: "needs-llvm-zstd",
|
name: "needs-llvm-zstd",
|
||||||
condition: cache.llvm_zstd,
|
condition: cache.llvm_zstd && config.default_codegen_backend.is_llvm(),
|
||||||
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression",
|
ignore_reason: "ignored if LLVM wasn't build with zstd for ELF section compression or LLVM is not the default codegen backend",
|
||||||
},
|
},
|
||||||
Need {
|
Need {
|
||||||
name: "needs-rustc-debug-assertions",
|
name: "needs-rustc-debug-assertions",
|
||||||
|
|
@ -279,7 +279,10 @@ pub(super) fn handle_needs(
|
||||||
|
|
||||||
// Handled elsewhere.
|
// Handled elsewhere.
|
||||||
if name == "needs-llvm-components" {
|
if name == "needs-llvm-components" {
|
||||||
return IgnoreDecision::Continue;
|
if config.default_codegen_backend.is_llvm() {
|
||||||
|
return IgnoreDecision::Continue;
|
||||||
|
}
|
||||||
|
return IgnoreDecision::Ignore { reason: "LLVM specific test".into() };
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut found_valid = false;
|
let mut found_valid = false;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ trait Get {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Other {
|
trait Other {
|
||||||
fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get, Self: Get {}
|
fn uhoh<U: Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Sized, Self: Get {}
|
||||||
//~^ ERROR the trait bound `Self: Get` is not satisfied
|
//~^ ERROR the trait bound `Self: Get` is not satisfied
|
||||||
//~| ERROR the trait bound `Self: Get` is not satisfied
|
//~| ERROR the trait bound `Self: Get` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ impl<T> ProjectedMyTrait for T
|
||||||
|
|
||||||
fn require_trait<T: MyTrait>(_: T) {}
|
fn require_trait<T: MyTrait>(_: T) {}
|
||||||
|
|
||||||
fn foo<T : MyTrait + 'static + 'static, U : MyTrait + 'static + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
|
fn foo<T : MyTrait + 'static, U : MyTrait + 'static>(wrap: Wrapper<'_, Option<T>>, wrap1: Wrapper<'_, Option<U>>) {
|
||||||
//~^ HELP consider restricting the type parameter to the `'static` lifetime
|
//~^ HELP consider restricting the type parameter to the `'static` lifetime
|
||||||
//~| HELP consider restricting the type parameter to the `'static` lifetime
|
//~| HELP consider restricting the type parameter to the `'static` lifetime
|
||||||
require_trait(wrap);
|
require_trait(wrap);
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ fn asteroids() -> impl FnOnce() -> bool {
|
||||||
|
|
||||||
// https://github.com/rust-lang/rust/issues/105179
|
// https://github.com/rust-lang/rust/issues/105179
|
||||||
fn r#match() -> i32 {
|
fn r#match() -> i32 {
|
||||||
((match () { () => 1 })) + match () { () => 1 } //~ ERROR expected expression, found `+`
|
(match () { () => 1 }) + match () { () => 1 } //~ ERROR expected expression, found `+`
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,7 +82,7 @@ fn matches() -> bool {
|
||||||
(match () { _ => true }) && match () { _ => true }; //~ ERROR mismatched types
|
(match () { _ => true }) && match () { _ => true }; //~ ERROR mismatched types
|
||||||
//~^ ERROR expected `;`, found keyword `match`
|
//~^ ERROR expected `;`, found keyword `match`
|
||||||
(match () { _ => true }) && true; //~ ERROR mismatched types
|
(match () { _ => true }) && true; //~ ERROR mismatched types
|
||||||
((match () { _ => true })) && true //~ ERROR mismatched types
|
(match () { _ => true }) && true //~ ERROR mismatched types
|
||||||
//~^ ERROR mismatched types
|
//~^ ERROR mismatched types
|
||||||
}
|
}
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,12 @@ extern crate dep;
|
||||||
use dep::*;
|
use dep::*;
|
||||||
|
|
||||||
struct Local;
|
struct Local;
|
||||||
|
|
||||||
impl Trait for Local {}
|
impl Trait for Local {}
|
||||||
//~^ ERROR not all trait items implemented
|
//~^ ERROR not all trait items implemented
|
||||||
//~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
|
//~| HELP implement the missing item: `fn foo(_: impl Sized) { todo!() }`
|
||||||
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
|
//~| HELP implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
|
||||||
|
//~| HELP implement the missing item: `fn baz<const N: usize>() { todo!() }`
|
||||||
|
//~| HELP implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
error[E0046]: not all trait items implemented, missing: `foo`, `bar`
|
error[E0046]: not all trait items implemented, missing: `foo`, `bar`, `baz`, `quux`
|
||||||
--> $DIR/apitit-unimplemented-method.rs:7:1
|
--> $DIR/apitit-unimplemented-method.rs:8:1
|
||||||
|
|
|
|
||||||
LL | impl Trait for Local {}
|
LL | impl Trait for Local {}
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar` in implementation
|
| ^^^^^^^^^^^^^^^^^^^^ missing `foo`, `bar`, `baz`, `quux` in implementation
|
||||||
|
|
|
|
||||||
= help: implement the missing item: `fn foo(_: impl Sized) { todo!() }`
|
= help: implement the missing item: `fn foo(_: impl Sized) { todo!() }`
|
||||||
= help: implement the missing item: `fn bar<T>(_: impl Sized) { todo!() }`
|
= help: implement the missing item: `fn bar<T>(_: impl Sized) where Foo<T>: MetaSized { todo!() }`
|
||||||
|
= help: implement the missing item: `fn baz<const N: usize>() { todo!() }`
|
||||||
|
= help: implement the missing item: `fn quux<'a: 'b, 'b, T>() where T: ?Sized { todo!() }`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,16 @@
|
||||||
|
#![feature(sized_hierarchy)]
|
||||||
|
|
||||||
|
use std::marker::MetaSized;
|
||||||
|
|
||||||
|
pub struct Foo<T> {
|
||||||
|
inner: T,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Trait {
|
pub trait Trait {
|
||||||
fn foo(_: impl Sized);
|
fn foo(_: impl Sized);
|
||||||
fn bar<T>(_: impl Sized);
|
fn bar<T>(_: impl Sized)
|
||||||
|
where
|
||||||
|
Foo<T>: MetaSized;
|
||||||
|
fn baz<'a, const N: usize>();
|
||||||
|
fn quux<'a: 'b, 'b, T: ?Sized>();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct AABB<K: Debug + std::marker::Copy + std::marker::Copy + std::marker::Copy + std::marker::Copy> {
|
pub struct AABB<K: Debug + std::marker::Copy> {
|
||||||
pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
|
pub loc: Vector2<K>, //~ ERROR the trait bound `K: Copy` is not satisfied
|
||||||
//~^ ERROR the trait bound `K: Copy` is not satisfied
|
//~^ ERROR the trait bound `K: Copy` is not satisfied
|
||||||
//~| ERROR the trait bound `K: Copy` is not satisfied
|
//~| ERROR the trait bound `K: Copy` is not satisfied
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ pub struct Vector2<T: Debug + Copy + Clone>{
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type
|
#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type
|
||||||
pub struct AABB<K: Copy + Debug + std::fmt::Debug + std::fmt::Debug + std::fmt::Debug>{
|
pub struct AABB<K: Copy + Debug + std::fmt::Debug>{
|
||||||
pub loc: Vector2<K>, //~ ERROR `K` doesn't implement `Debug`
|
pub loc: Vector2<K>, //~ ERROR `K` doesn't implement `Debug`
|
||||||
//~^ ERROR `K` doesn't implement `Debug`
|
//~^ ERROR `K` doesn't implement `Debug`
|
||||||
pub size: Vector2<K> //~ ERROR `K` doesn't implement `Debug`
|
pub size: Vector2<K> //~ ERROR `K` doesn't implement `Debug`
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ struct ConstrainedStruct<X: Copy> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy, X: std::marker::Copy {
|
trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::Copy {
|
||||||
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
|
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
|
||||||
//~^ ERROR the trait bound `X: Copy` is not satisfied
|
//~^ ERROR the trait bound `X: Copy` is not satisfied
|
||||||
ConstrainedStruct { x }
|
ConstrainedStruct { x }
|
||||||
|
|
@ -20,7 +20,7 @@ trait InsufficientlyConstrainedGeneric<X=()> where Self: Sized, X: std::marker::
|
||||||
|
|
||||||
// Regression test for #120838
|
// Regression test for #120838
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy, X: std::marker::Copy {
|
trait InsufficientlyConstrainedGenericWithEmptyWhere<X=()> where Self: Sized, X: std::marker::Copy {
|
||||||
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
|
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
|
||||||
//~^ ERROR the trait bound `X: Copy` is not satisfied
|
//~^ ERROR the trait bound `X: Copy` is not satisfied
|
||||||
ConstrainedStruct { x }
|
ConstrainedStruct { x }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue