Skip to content

Rollup of 6 pull requests #120623

New issue

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

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

Already on GitHub? # to your account

Closed
wants to merge 24 commits into from
Closed
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9099c94
Use a better set of targets for blessing mir-opt tests
saethlin Jan 7, 2024
3ea464f
Add tests
Nadrieril Jan 21, 2024
96ff1a4
Move `Or` test out of the loop
Nadrieril Jan 21, 2024
e902878
Clarify the binding dance
Nadrieril Jan 21, 2024
09d4613
Put new bindings first in refutable cases too
Nadrieril Jan 21, 2024
0825ad3
Clarify the new binding dance
Nadrieril Jan 21, 2024
cda3588
make matching on NaN a hard error
RalfJung Sep 30, 2023
1254ee4
remove illegal_floating_point_literal_pattern lint
RalfJung Jan 6, 2024
9f14fc4
add test checking behavior of matching on floats, and NaNs in consts
RalfJung Sep 23, 2023
c367983
Suggest name value cfg when only value is used for check-cfg
chenyukang Jan 28, 2024
0213c87
limit the names_possiblilities to less than 3
chenyukang Jan 30, 2024
ca243e7
add testcase for more than 3 cfg names
chenyukang Jan 30, 2024
d34b0fa
Add test for method on unbounded type parameter receiver
estebank Jan 26, 2024
20b1c2a
Account for unbounded type param receiver in suggestions
estebank Jan 26, 2024
9ccc770
fix rebase
estebank Jan 30, 2024
f622e83
Actually abort in panic-abort-tests
tmandry Jan 24, 2024
815d312
Tweak a few mir-opt tests instead of using -Clink-dead-code
saethlin Jan 31, 2024
48f664b
Ignore test-panic-abort tests on Android
tmandry Feb 2, 2024
0cb975e
Rollup merge of #116284 - RalfJung:no-nan-match, r=cjgillot
matthiaskrgr Feb 3, 2024
d4c48be
Rollup merge of #120060 - saethlin:mir-opt-bless-targets, r=wesleywiser
matthiaskrgr Feb 3, 2024
a637087
Rollup merge of #120214 - Nadrieril:fix-120210, r=pnkfelix
matthiaskrgr Feb 3, 2024
b810fa6
Rollup merge of #120326 - tmandry:abort-in-tests, r=cuviper
matthiaskrgr Feb 3, 2024
3655eee
Rollup merge of #120396 - estebank:method-on-unbounded-type-param, r=…
matthiaskrgr Feb 3, 2024
6677374
Rollup merge of #120435 - chenyukang:yukang-fix-120427-cfg-name, r=Ur…
matthiaskrgr Feb 3, 2024
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -5321,6 +5321,7 @@ version = "0.0.0"
dependencies = [
"core",
"getopts",
"libc",
"panic_abort",
"panic_unwind",
"std",
41 changes: 27 additions & 14 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
@@ -554,6 +554,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
));
}
} else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) {
// We special case the situation where we are looking for `_` in
// `<TypeParam as _>::method` because otherwise the machinery will look for blanket
// implementations that have unsatisfied trait bounds to suggest, leading us to claim
// things like "we're looking for a trait with method `cmp`, both `Iterator` and `Ord`
// have one, in order to implement `Ord` you need to restrict `TypeParam: FnPtr` so
// that `impl<T: FnPtr> Ord for T` can apply", which is not what we want. We have a type
// parameter, we want to directly say "`Ord::cmp` and `Iterator::cmp` exist, restrict
// `TypeParam: Ord` or `TypeParam: Iterator`"". That is done further down when calling
// `self.suggest_traits_to_import`, so we ignore the `unsatisfied_predicates`
// suggestions.
} else if !unsatisfied_predicates.is_empty() {
let mut type_params = FxIndexMap::default();

@@ -1325,7 +1336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
return Some(err);
Some(err)
}

fn note_candidates_on_method_error(
@@ -2918,19 +2929,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// this isn't perfect (that is, there are cases when
// implementing a trait would be legal but is rejected
// here).
unsatisfied_predicates.iter().all(|(p, _, _)| {
match p.kind().skip_binder() {
// Hide traits if they are present in predicates as they can be fixed without
// having to implement them.
ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
t.def_id() == info.def_id
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => {
p.projection_ty.def_id == info.def_id
}
_ => false,
}
}) && (type_is_local || info.def_id.is_local())
(type_is_local || info.def_id.is_local())
&& !self.tcx.trait_is_auto(info.def_id)
&& self
.associated_value(info.def_id, item_name)
@@ -2978,6 +2977,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item.visibility(self.tcx).is_public() || info.def_id.is_local()
})
.is_some()
&& (matches!(rcvr_ty.kind(), ty::Param(_))
|| unsatisfied_predicates.iter().all(|(p, _, _)| {
match p.kind().skip_binder() {
// Hide traits if they are present in predicates as they can be fixed without
// having to implement them.
ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
t.def_id() == info.def_id
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => {
p.projection_ty.def_id == info.def_id
}
_ => false,
}
}))
})
.collect::<Vec<_>>();
for span in &arbitrary_rcvr {
50 changes: 40 additions & 10 deletions compiler/rustc_lint/src/context/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -188,6 +188,23 @@ pub(super) fn builtin(
#[allow(rustc::potential_query_instability)]
let possibilities: Vec<Symbol> =
sess.parse_sess.check_config.expecteds.keys().copied().collect();

let mut names_possibilities: Vec<_> = if value.is_none() {
// We later sort and display all the possibilities, so the order here does not matter.
#[allow(rustc::potential_query_instability)]
sess.parse_sess
.check_config
.expecteds
.iter()
.filter_map(|(k, v)| match v {
ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k),
_ => None,
})
.collect()
} else {
Vec::new()
};

let is_from_cargo = std::env::var_os("CARGO").is_some();
let mut is_feature_cfg = name == sym::feature;

@@ -262,17 +279,30 @@ pub(super) fn builtin(
}

is_feature_cfg |= best_match == sym::feature;
} else if !possibilities.is_empty() {
let mut possibilities =
possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
possibilities.sort();
let possibilities = possibilities.join("`, `");
} else {
if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
names_possibilities.sort();
for cfg_name in names_possibilities.iter() {
db.span_suggestion(
name_span,
"found config with similar value",
format!("{cfg_name} = \"{name}\""),
Applicability::MaybeIncorrect,
);
}
}
if !possibilities.is_empty() {
let mut possibilities =
possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
possibilities.sort();
let possibilities = possibilities.join("`, `");

// The list of expected names can be long (even by default) and
// so the diagnostic produced can take a lot of space. To avoid
// cloging the user output we only want to print that diagnostic
// once.
db.help_once(format!("expected names are: `{possibilities}`"));
// The list of expected names can be long (even by default) and
// so the diagnostic produced can take a lot of space. To avoid
// cloging the user output we only want to print that diagnostic
// once.
db.help_once(format!("expected names are: `{possibilities}`"));
}
}

let inst = if let Some((value, _value_span)) = value {
4 changes: 4 additions & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -516,6 +516,10 @@ fn register_builtins(store: &mut LintStore) {
"converted into hard error, see PR #118649 \
<https://github.com/rust-lang/rust/pull/118649> for more information",
);
store.register_removed(
"illegal_floating_point_literal_pattern",
"no longer a warning, float patterns behave the same as `==`",
);
}

fn register_internals(store: &mut LintStore) {
50 changes: 0 additions & 50 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -45,7 +45,6 @@ declare_lint_pass! {
FUZZY_PROVENANCE_CASTS,
HIDDEN_GLOB_REEXPORTS,
ILL_FORMED_ATTRIBUTE_INPUT,
ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
INCOMPLETE_INCLUDE,
INDIRECT_STRUCTURAL_MATCH,
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
@@ -1873,55 +1872,6 @@ declare_lint! {
};
}

declare_lint! {
/// The `illegal_floating_point_literal_pattern` lint detects
/// floating-point literals used in patterns.
///
/// ### Example
///
/// ```rust
/// let x = 42.0;
///
/// match x {
/// 5.0 => {}
/// _ => {}
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// Previous versions of the compiler accepted floating-point literals in
/// patterns, but it was later determined this was a mistake. The
/// semantics of comparing floating-point values may not be clear in a
/// pattern when contrasted with "structural equality". Typically you can
/// work around this by using a [match guard], such as:
///
/// ```rust
/// # let x = 42.0;
///
/// match x {
/// y if y == 5.0 => {}
/// _ => {}
/// }
/// ```
///
/// This is a [future-incompatible] lint to transition this to a hard
/// error in the future. See [issue #41620] for more details.
///
/// [issue #41620]: https://github.com/rust-lang/rust/issues/41620
/// [match guard]: https://doc.rust-lang.org/reference/expressions/match-expr.html#match-guards
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
Warn,
"floating-point literals cannot be used in patterns",
@future_incompatible = FutureIncompatibleInfo {
reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
};
}

declare_lint! {
/// The `unstable_name_collisions` lint detects that you have used a name
/// that the standard library plans to add in the future.
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/mir/interpret/value.rs
Original file line number Diff line number Diff line change
@@ -418,8 +418,8 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {

#[inline]
pub fn to_float<F: Float>(self) -> InterpResult<'tcx, F> {
// Going through `to_uint` to check size and truncation.
Ok(F::from_bits(self.to_uint(Size::from_bits(F::BITS))?))
// Going through `to_bits` to check size and truncation.
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
}

#[inline]
71 changes: 44 additions & 27 deletions compiler/rustc_middle/src/ty/consts/int.rs
Original file line number Diff line number Diff line change
@@ -249,11 +249,6 @@ impl ScalarInt {
}
}

#[inline]
pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
Ok(self.to_bits(tcx.data_layout.pointer_size)? as u64)
}

/// Tries to convert the `ScalarInt` to an unsigned integer of the given size.
/// Fails if the size of the `ScalarInt` is not equal to `size` and returns the
/// `ScalarInt`s size in that case.
@@ -262,56 +257,61 @@ impl ScalarInt {
self.to_bits(size)
}

// Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
// in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size`
// value of the `ScalarInt` in that case.
#[inline]
pub fn try_to_bool(self) -> Result<bool, Size> {
match self.try_to_u8()? {
0 => Ok(false),
1 => Ok(true),
_ => Err(self.size()),
}
}

// Tries to convert the `ScalarInt` to `u8`. Fails if the `size` of the `ScalarInt`
// in not equal to `Size { raw: 1 }` and returns the `size` value of the `ScalarInt` in
// that case.
#[inline]
pub fn try_to_u8(self) -> Result<u8, Size> {
self.to_bits(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
self.try_to_uint(Size::from_bits(8)).map(|v| u8::try_from(v).unwrap())
}

/// Tries to convert the `ScalarInt` to `u16`. Fails if the size of the `ScalarInt`
/// in not equal to `Size { raw: 2 }` and returns the `size` value of the `ScalarInt` in
/// that case.
#[inline]
pub fn try_to_u16(self) -> Result<u16, Size> {
self.to_bits(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
self.try_to_uint(Size::from_bits(16)).map(|v| u16::try_from(v).unwrap())
}

/// Tries to convert the `ScalarInt` to `u32`. Fails if the `size` of the `ScalarInt`
/// in not equal to `Size { raw: 4 }` and returns the `size` value of the `ScalarInt` in
/// that case.
#[inline]
pub fn try_to_u32(self) -> Result<u32, Size> {
self.to_bits(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
self.try_to_uint(Size::from_bits(32)).map(|v| u32::try_from(v).unwrap())
}

/// Tries to convert the `ScalarInt` to `u64`. Fails if the `size` of the `ScalarInt`
/// in not equal to `Size { raw: 8 }` and returns the `size` value of the `ScalarInt` in
/// that case.
#[inline]
pub fn try_to_u64(self) -> Result<u64, Size> {
self.to_bits(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
self.try_to_uint(Size::from_bits(64)).map(|v| u64::try_from(v).unwrap())
}

/// Tries to convert the `ScalarInt` to `u128`. Fails if the `size` of the `ScalarInt`
/// in not equal to `Size { raw: 16 }` and returns the `size` value of the `ScalarInt` in
/// that case.
#[inline]
pub fn try_to_u128(self) -> Result<u128, Size> {
self.to_bits(Size::from_bits(128))
self.try_to_uint(Size::from_bits(128))
}

#[inline]
pub fn try_to_target_usize(&self, tcx: TyCtxt<'_>) -> Result<u64, Size> {
self.try_to_uint(tcx.data_layout.pointer_size).map(|v| u64::try_from(v).unwrap())
}

// Tries to convert the `ScalarInt` to `bool`. Fails if the `size` of the `ScalarInt`
// in not equal to `Size { raw: 1 }` or if the value is not 0 or 1 and returns the `size`
// value of the `ScalarInt` in that case.
#[inline]
pub fn try_to_bool(self) -> Result<bool, Size> {
match self.try_to_u8()? {
0 => Ok(false),
1 => Ok(true),
_ => Err(self.size()),
}
}

/// Tries to convert the `ScalarInt` to a signed integer of the given size.
@@ -357,6 +357,27 @@ impl ScalarInt {
pub fn try_to_i128(self) -> Result<i128, Size> {
self.try_to_int(Size::from_bits(128))
}

#[inline]
pub fn try_to_target_isize(&self, tcx: TyCtxt<'_>) -> Result<i64, Size> {
self.try_to_int(tcx.data_layout.pointer_size).map(|v| i64::try_from(v).unwrap())
}

#[inline]
pub fn try_to_float<F: Float>(self) -> Result<F, Size> {
// Going through `to_uint` to check size and truncation.
Ok(F::from_bits(self.to_bits(Size::from_bits(F::BITS))?))
}

#[inline]
pub fn try_to_f32(self) -> Result<Single, Size> {
self.try_to_float()
}

#[inline]
pub fn try_to_f64(self) -> Result<Double, Size> {
self.try_to_float()
}
}

macro_rules! from {
@@ -399,11 +420,7 @@ impl TryFrom<ScalarInt> for bool {
type Error = Size;
#[inline]
fn try_from(int: ScalarInt) -> Result<Self, Size> {
int.to_bits(Size::from_bytes(1)).and_then(|u| match u {
0 => Ok(false),
1 => Ok(true),
_ => Err(Size::from_bytes(1)),
})
int.try_to_bool()
}
}

6 changes: 4 additions & 2 deletions compiler/rustc_mir_build/messages.ftl
Original file line number Diff line number Diff line change
@@ -107,8 +107,6 @@ mir_build_extern_static_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
.label = use of extern static

mir_build_float_pattern = floating-point types cannot be used in patterns

mir_build_indirect_structural_match =
to use a constant of type `{$non_sm_ty}` in a pattern, `{$non_sm_ty}` must be annotated with `#[derive(PartialEq)]`

@@ -232,6 +230,10 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa
.note = mutating layout constrained fields cannot statically be checked for valid values
.label = mutation of layout constrained field

mir_build_nan_pattern = cannot use NaN in patterns
.note = NaNs compare inequal to everything, even themselves, so this pattern would never match
.help = try using the `is_nan` method instead

mir_build_non_const_path = runtime values cannot be referenced in patterns

mir_build_non_empty_never_pattern =
Loading