Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #125203

Merged
merged 12 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/rustc_expand/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ expand_attribute_meta_item =
expand_attribute_single_word =
attribute must only be a single word

expand_attributes_on_expressions_experimental =
attributes on expressions are experimental
.help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//`
.help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`

expand_attributes_wrong_form =
attribute must be of form: `attributes(foo, bar)`

Expand Down
9 changes: 6 additions & 3 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,6 @@ impl<'a> StripUnconfigured<'a> {
}

/// If attributes are not allowed on expressions, emit an error for `attr`
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
#[instrument(level = "trace", skip(self))]
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
if self.features.is_some_and(|features| !features.stmt_expr_attributes)
Expand All @@ -392,11 +391,15 @@ impl<'a> StripUnconfigured<'a> {
&self.sess,
sym::stmt_expr_attributes,
attr.span,
"attributes on expressions are experimental",
crate::fluent_generated::expand_attributes_on_expressions_experimental,
);

if attr.is_doc_comment() {
err.help("`///` is for documentation comments. For a plain comment, use `//`.");
err.help(if attr.style == AttrStyle::Outer {
crate::fluent_generated::expand_help_outer_doc
} else {
crate::fluent_generated::expand_help_inner_doc
});
}

err.emit();
Expand Down
77 changes: 57 additions & 20 deletions compiler/rustc_trait_selection/src/solve/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,39 +384,64 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
return ControlFlow::Break(self.obligation.clone());
}

// FIXME: Could we extract a trait ref from a projection here too?
let tcx = goal.infcx().tcx;
// FIXME: Also, what about considering >1 layer up the stack? May be necessary
// for normalizes-to.
let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else {
return ControlFlow::Break(self.obligation.clone());
let pred_kind = goal.goal().predicate.kind();
let child_mode = match pred_kind.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(parent_trait_pred)) => {
ChildMode::Trait(pred_kind.rebind(parent_trait_pred))
}
ty::PredicateKind::NormalizesTo(normalizes_to)
if matches!(
normalizes_to.alias.kind(tcx),
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst
) =>
{
ChildMode::Trait(pred_kind.rebind(ty::TraitPredicate {
trait_ref: normalizes_to.alias.trait_ref(tcx),
polarity: ty::PredicatePolarity::Positive,
}))
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => {
ChildMode::WellFormedObligation
}
_ => {
return ControlFlow::Break(self.obligation.clone());
}
};

let tcx = goal.infcx().tcx;
let mut impl_where_bound_count = 0;
for nested_goal in candidate.instantiate_nested_goals(self.span()) {
let make_obligation = |cause| Obligation {
cause,
param_env: nested_goal.goal().param_env,
predicate: nested_goal.goal().predicate,
recursion_depth: self.obligation.recursion_depth + 1,
};

let obligation;
match nested_goal.source() {
GoalSource::Misc => {
match (child_mode, nested_goal.source()) {
(ChildMode::Trait(_), GoalSource::Misc) => {
continue;
}
GoalSource::ImplWhereBound => {
obligation = Obligation {
cause: derive_cause(
tcx,
candidate.kind(),
self.obligation.cause.clone(),
impl_where_bound_count,
parent_trait_pred,
),
param_env: nested_goal.goal().param_env,
predicate: nested_goal.goal().predicate,
recursion_depth: self.obligation.recursion_depth + 1,
};
(ChildMode::Trait(parent_trait_pred), GoalSource::ImplWhereBound) => {
obligation = make_obligation(derive_cause(
tcx,
candidate.kind(),
self.obligation.cause.clone(),
impl_where_bound_count,
parent_trait_pred,
));
impl_where_bound_count += 1;
}
GoalSource::InstantiateHigherRanked => {
// Skip over a higher-ranked predicate.
(_, GoalSource::InstantiateHigherRanked) => {
obligation = self.obligation.clone();
}
(ChildMode::WellFormedObligation, _) => {
obligation = make_obligation(self.obligation.cause.clone());
}
}

// Skip nested goals that aren't the *reason* for our goal's failure.
Expand All @@ -436,6 +461,18 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
}
}

#[derive(Copy, Clone)]
enum ChildMode<'tcx> {
// Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`,
// and skip all `GoalSource::Misc`, which represent useless obligations
// such as alias-eq which may not hold.
Trait(ty::PolyTraitPredicate<'tcx>),
// Skip trying to derive an `ObligationCause` from this obligation, and
// report *all* sub-obligations as if they came directly from the parent
// obligation.
WellFormedObligation,
}

fn derive_cause<'tcx>(
tcx: TyCtxt<'tcx>,
candidate_kind: ProbeKind<'tcx>,
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ impl<T: ?Sized> *mut T {
///
/// This is similar to `self as usize`, which semantically discards *provenance* and
/// *address-space* information. However, unlike `self as usize`, casting the returned address
/// back to a pointer yields yields a [pointer without provenance][without_provenance_mut], which is undefined
/// back to a pointer yields a [pointer without provenance][without_provenance_mut], which is undefined
/// behavior to dereference. To properly restore the lost information and obtain a
/// dereferenceable pointer, use [`with_addr`][pointer::with_addr] or
/// [`map_addr`][pointer::map_addr].
Expand Down
16 changes: 8 additions & 8 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4533,21 +4533,21 @@ impl<T, const N: usize> [[T; N]] {
/// ```
/// #![feature(slice_flatten)]
///
/// assert_eq!([[1, 2, 3], [4, 5, 6]].flatten(), &[1, 2, 3, 4, 5, 6]);
/// assert_eq!([[1, 2, 3], [4, 5, 6]].as_flattened(), &[1, 2, 3, 4, 5, 6]);
///
/// assert_eq!(
/// [[1, 2, 3], [4, 5, 6]].flatten(),
/// [[1, 2], [3, 4], [5, 6]].flatten(),
/// [[1, 2, 3], [4, 5, 6]].as_flattened(),
/// [[1, 2], [3, 4], [5, 6]].as_flattened(),
/// );
///
/// let slice_of_empty_arrays: &[[i32; 0]] = &[[], [], [], [], []];
/// assert!(slice_of_empty_arrays.flatten().is_empty());
/// assert!(slice_of_empty_arrays.as_flattened().is_empty());
///
/// let empty_slice_of_arrays: &[[u32; 10]] = &[];
/// assert!(empty_slice_of_arrays.flatten().is_empty());
/// assert!(empty_slice_of_arrays.as_flattened().is_empty());
/// ```
#[unstable(feature = "slice_flatten", issue = "95629")]
pub const fn flatten(&self) -> &[T] {
pub const fn as_flattened(&self) -> &[T] {
let len = if T::IS_ZST {
self.len().checked_mul(N).expect("slice len overflow")
} else {
Expand Down Expand Up @@ -4581,11 +4581,11 @@ impl<T, const N: usize> [[T; N]] {
/// }
///
/// let mut array = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
/// add_5_to_all(array.flatten_mut());
/// add_5_to_all(array.as_flattened_mut());
/// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]);
/// ```
#[unstable(feature = "slice_flatten", issue = "95629")]
pub fn flatten_mut(&mut self) -> &mut [T] {
pub fn as_flattened_mut(&mut self) -> &mut [T] {
let len = if T::IS_ZST {
self.len().checked_mul(N).expect("slice len overflow")
} else {
Expand Down
4 changes: 2 additions & 2 deletions library/core/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2609,14 +2609,14 @@ fn test_slice_from_ptr_range() {
#[should_panic = "slice len overflow"]
fn test_flatten_size_overflow() {
let x = &[[(); usize::MAX]; 2][..];
let _ = x.flatten();
let _ = x.as_flattened();
}

#[test]
#[should_panic = "slice len overflow"]
fn test_flatten_mut_size_overflow() {
let x = &mut [[(); usize::MAX]; 2][..];
let _ = x.flatten_mut();
let _ = x.as_flattened_mut();
}

#[test]
Expand Down
11 changes: 9 additions & 2 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,9 @@ impl Config {
toml_path = config.src.join(toml_path);
}

let file_content = t!(fs::read_to_string(config.src.join("src/ci/channel")));
let ci_channel = file_content.trim_end();

// Give a hard error if `--config` or `RUST_BOOTSTRAP_CONFIG` are set to a missing path,
// but not if `config.toml` hasn't been created.
let mut toml = if !using_default_path || toml_path.exists() {
Expand Down Expand Up @@ -1534,6 +1537,7 @@ impl Config {
let mut omit_git_hash = None;
let mut lld_enabled = None;

let mut is_user_configured_rust_channel = false;
if let Some(rust) = toml.rust {
let Rust {
optimize: optimize_toml,
Expand Down Expand Up @@ -1591,15 +1595,14 @@ impl Config {
lld_mode,
} = rust;

is_user_configured_rust_channel = channel.is_some();
set(&mut config.channel, channel);

config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc);
// This list is incomplete, please help by expanding it!
if config.download_rustc_commit.is_some() {
// We need the channel used by the downloaded compiler to match the one we set for rustdoc;
// otherwise rustdoc-ui tests break.
let ci_channel = t!(fs::read_to_string(config.src.join("src/ci/channel")));
let ci_channel = ci_channel.trim_end();
if config.channel != ci_channel
&& !(config.channel == "dev" && ci_channel == "nightly")
{
Expand Down Expand Up @@ -1717,6 +1720,10 @@ impl Config {
config.omit_git_hash = omit_git_hash.unwrap_or(default);
config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);

if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel {
ci_channel.clone_into(&mut config.channel);
}

if let Some(llvm) = toml.llvm {
let Llvm {
optimize: optimize_toml,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
error: the type `Foo::Bar<Vec<[u32]>>` is not well-formed
--> $DIR/wf-check-skipped.rs:17:14
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
--> $DIR/wf-check-skipped.rs:17:25
|
LL | fn main() -> Foo::Bar::<Vec<[u32]>> {}
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `[u32]`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ impl Foo {
}

fn main() -> Foo::Bar::<Vec<[u32]>> {}
//[next]~^ ERROR the type `Foo::Bar<Vec<[u32]>>` is not well-formed
//[next]~^ ERROR the size for values of type `[u32]` cannot be known at compilation time
11 changes: 11 additions & 0 deletions tests/ui/feature-gates/feature-gate-stmt_expr_attributes.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
const X: i32 = #[allow(dead_code)] 8;
//~^ ERROR attributes on expressions are experimental

const Y: i32 =
/// foo
//~^ ERROR attributes on expressions are experimental
8;

const Z: i32 = {
//! foo
//~^ ERROR attributes on expressions are experimental
8
};

fn main() {}
24 changes: 23 additions & 1 deletion tests/ui/feature-gates/feature-gate-stmt_expr_attributes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,28 @@ LL | const X: i32 = #[allow(dead_code)] 8;
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: aborting due to 1 previous error
error[E0658]: attributes on expressions are experimental
--> $DIR/feature-gate-stmt_expr_attributes.rs:5:5
|
LL | /// foo
| ^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` 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: `///` is used for outer documentation comments; for a plain comment, use `//`

error[E0658]: attributes on expressions are experimental
--> $DIR/feature-gate-stmt_expr_attributes.rs:10:5
|
LL | //! foo
| ^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` 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: `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0658`.
20 changes: 1 addition & 19 deletions tests/ui/for/issue-20605.next.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,13 @@ help: consider mutably borrowing here
LL | for item in &mut *things { *item = 0 }
| ++++

error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:6:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^

error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:6:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^

error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
--> $DIR/issue-20605.rs:6:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^

error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
--> $DIR/issue-20605.rs:6:27
|
LL | for item in *things { *item = 0 }
| ^^^^^

error: aborting due to 5 previous errors
error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0614.
For more information about an error, try `rustc --explain E0277`.
3 changes: 0 additions & 3 deletions tests/ui/for/issue-20605.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
for item in *things { *item = 0 }
//[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
//[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
//[next]~| ERROR type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced

// FIXME(-Znext-solver): these error messages are horrible and have to be
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ struct W<T>(T);
// `usize: Foo` doesn't hold. Therefore we ICE, because we don't expect to still
// encounter weak types in `assemble_alias_bound_candidates_recur`.
fn hello(_: W<A<usize>>) {}
//~^ ERROR the type `W<A<usize>>` is not well-formed
//~^ ERROR the size for values of type `A<usize>` cannot be known at compilation time

fn main() {}
7 changes: 5 additions & 2 deletions tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ LL | #![feature(lazy_type_alias)]
= note: see issue #112792 <https://github.com/rust-lang/rust/issues/112792> for more information
= note: `#[warn(incomplete_features)]` on by default

error: the type `W<A<usize>>` is not well-formed
error[E0277]: the size for values of type `A<usize>` cannot be known at compilation time
--> $DIR/alias-bounds-when-not-wf.rs:16:13
|
LL | fn hello(_: W<A<usize>>) {}
| ^^^^^^^^^^^
| ^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `A<usize>`

error: aborting due to 1 previous error; 1 warning emitted

For more information about this error, try `rustc --explain E0277`.
2 changes: 1 addition & 1 deletion tests/ui/lint/unused/unused-doc-comments-edge-cases.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LL | (/// useless doc comment
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` 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: `///` is for documentation comments. For a plain comment, use `//`.
= help: `///` is used for outer documentation comments; for a plain comment, use `//`

error: unused doc comment
--> $DIR/unused-doc-comments-edge-cases.rs:6:9
Expand Down
Loading
Loading