Auto merge of #112253 - matthiaskrgr:rollup-c37jpm5, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #111659 (suggest `Option::as_deref(_mut)` on type mismatch in option combinator if it passes typeck) - #111702 (Option::map_or_else: Show an example of integrating with Result) - #111878 (Fix codegen test suite for bare-metal-like targets) - #111969 (bootstrap: Make `clean` respect `dry-run`) - #111998 (Add other workspaces to `linkedProjects` in rust_analyzer_settings) - #112215 (only suppress coercion error if type is definitely unsized) - #112231 (Make sure the build.rustc version is either the same or 1 apart (revised)) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
398fa2187c
@ -1595,7 +1595,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
Some(blk_id),
|
||||
);
|
||||
if !fcx.tcx.features().unsized_locals {
|
||||
unsized_return = self.is_return_ty_unsized(fcx, blk_id);
|
||||
unsized_return = self.is_return_ty_definitely_unsized(fcx);
|
||||
}
|
||||
if let Some(expression) = expression
|
||||
&& let hir::ExprKind::Loop(loop_blk, ..) = expression.kind {
|
||||
@ -1614,8 +1614,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
None,
|
||||
);
|
||||
if !fcx.tcx.features().unsized_locals {
|
||||
let id = fcx.tcx.hir().parent_id(id);
|
||||
unsized_return = self.is_return_ty_unsized(fcx, id);
|
||||
unsized_return = self.is_return_ty_definitely_unsized(fcx);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -1896,15 +1895,24 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
err.help("you could instead create a new `enum` with a variant for each returned type");
|
||||
}
|
||||
|
||||
fn is_return_ty_unsized<'a>(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool {
|
||||
if let Some((_, fn_decl, _)) = fcx.get_fn_decl(blk_id)
|
||||
&& let hir::FnRetTy::Return(ty) = fn_decl.output
|
||||
&& let ty = fcx.astconv().ast_ty_to_ty( ty)
|
||||
&& let ty::Dynamic(..) = ty.kind()
|
||||
{
|
||||
return true;
|
||||
/// Checks whether the return type is unsized via an obligation, which makes
|
||||
/// sure we consider `dyn Trait: Sized` where clauses, which are trivially
|
||||
/// false but technically valid for typeck.
|
||||
fn is_return_ty_definitely_unsized(&self, fcx: &FnCtxt<'_, 'tcx>) -> bool {
|
||||
if let Some(sig) = fcx.body_fn_sig() {
|
||||
!fcx.predicate_may_hold(&Obligation::new(
|
||||
fcx.tcx,
|
||||
ObligationCause::dummy(),
|
||||
fcx.param_env,
|
||||
ty::TraitRef::new(
|
||||
fcx.tcx,
|
||||
fcx.tcx.require_lang_item(hir::LangItem::Sized, None),
|
||||
[sig.output()],
|
||||
),
|
||||
))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Ty<'tcx> {
|
||||
|
@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{
|
||||
error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
|
||||
ErrorGuaranteed, MultiSpan, Style,
|
||||
ErrorGuaranteed, MultiSpan, Style, SuggestionStyle,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
@ -362,6 +362,15 @@ pub trait TypeErrCtxtExt<'tcx> {
|
||||
err: &mut Diagnostic,
|
||||
trait_pred: ty::PolyTraitPredicate<'tcx>,
|
||||
);
|
||||
|
||||
fn suggest_option_method_if_applicable(
|
||||
&self,
|
||||
failed_pred: ty::Predicate<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
);
|
||||
|
||||
fn note_function_argument_obligation(
|
||||
&self,
|
||||
body_id: LocalDefId,
|
||||
@ -3521,15 +3530,92 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
err.replace_span_with(path.ident.span, true);
|
||||
}
|
||||
}
|
||||
if let Some(Node::Expr(hir::Expr {
|
||||
kind:
|
||||
hir::ExprKind::Call(hir::Expr { span, .. }, _)
|
||||
| hir::ExprKind::MethodCall(hir::PathSegment { ident: Ident { span, .. }, .. }, ..),
|
||||
..
|
||||
})) = hir.find(call_hir_id)
|
||||
|
||||
if let Some(Node::Expr(expr)) = hir.find(call_hir_id) {
|
||||
if let hir::ExprKind::Call(hir::Expr { span, .. }, _)
|
||||
| hir::ExprKind::MethodCall(
|
||||
hir::PathSegment { ident: Ident { span, .. }, .. },
|
||||
..,
|
||||
) = expr.kind
|
||||
{
|
||||
if Some(*span) != err.span.primary_span() {
|
||||
err.span_label(*span, "required by a bound introduced by this call");
|
||||
}
|
||||
}
|
||||
|
||||
if let hir::ExprKind::MethodCall(_, expr, ..) = expr.kind {
|
||||
self.suggest_option_method_if_applicable(failed_pred, param_env, err, expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_option_method_if_applicable(
|
||||
&self,
|
||||
failed_pred: ty::Predicate<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
) {
|
||||
let tcx = self.tcx;
|
||||
let infcx = self.infcx;
|
||||
let Some(typeck_results) = self.typeck_results.as_ref() else { return };
|
||||
|
||||
// Make sure we're dealing with the `Option` type.
|
||||
let Some(option_ty_adt) = typeck_results.expr_ty_adjusted(expr).ty_adt_def() else { return };
|
||||
if !tcx.is_diagnostic_item(sym::Option, option_ty_adt.did()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Given the predicate `fn(&T): FnOnce<(U,)>`, extract `fn(&T)` and `(U,)`,
|
||||
// then suggest `Option::as_deref(_mut)` if `U` can deref to `T`
|
||||
if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate { trait_ref, .. }))
|
||||
= failed_pred.kind().skip_binder()
|
||||
&& tcx.is_fn_trait(trait_ref.def_id)
|
||||
&& let [self_ty, found_ty] = trait_ref.substs.as_slice()
|
||||
&& let Some(fn_ty) = self_ty.as_type().filter(|ty| ty.is_fn())
|
||||
&& let fn_sig @ ty::FnSig {
|
||||
abi: abi::Abi::Rust,
|
||||
c_variadic: false,
|
||||
unsafety: hir::Unsafety::Normal,
|
||||
..
|
||||
} = fn_ty.fn_sig(tcx).skip_binder()
|
||||
|
||||
// Extract first param of fn sig with peeled refs, e.g. `fn(&T)` -> `T`
|
||||
&& let Some(&ty::Ref(_, target_ty, needs_mut)) = fn_sig.inputs().first().map(|t| t.kind())
|
||||
&& !target_ty.has_escaping_bound_vars()
|
||||
|
||||
// Extract first tuple element out of fn trait, e.g. `FnOnce<(U,)>` -> `U`
|
||||
&& let Some(ty::Tuple(tys)) = found_ty.as_type().map(Ty::kind)
|
||||
&& let &[found_ty] = tys.as_slice()
|
||||
&& !found_ty.has_escaping_bound_vars()
|
||||
|
||||
// Extract `<U as Deref>::Target` assoc type and check that it is `T`
|
||||
&& let Some(deref_target_did) = tcx.lang_items().deref_target()
|
||||
&& let projection = tcx.mk_projection(deref_target_did, tcx.mk_substs(&[ty::GenericArg::from(found_ty)]))
|
||||
&& let Ok(deref_target) = tcx.try_normalize_erasing_regions(param_env, projection)
|
||||
&& deref_target == target_ty
|
||||
{
|
||||
if Some(*span) != err.span.primary_span() {
|
||||
err.span_label(*span, "required by a bound introduced by this call");
|
||||
let help = if let hir::Mutability::Mut = needs_mut
|
||||
&& let Some(deref_mut_did) = tcx.lang_items().deref_mut_trait()
|
||||
&& infcx
|
||||
.type_implements_trait(deref_mut_did, iter::once(found_ty), param_env)
|
||||
.must_apply_modulo_regions()
|
||||
{
|
||||
Some(("call `Option::as_deref_mut()` first", ".as_deref_mut()"))
|
||||
} else if let hir::Mutability::Not = needs_mut {
|
||||
Some(("call `Option::as_deref()` first", ".as_deref()"))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if let Some((msg, sugg)) = help {
|
||||
err.span_suggestion_with_style(
|
||||
expr.span.shrink_to_hi(),
|
||||
msg,
|
||||
sugg,
|
||||
Applicability::MaybeIncorrect,
|
||||
SuggestionStyle::ShowAlways
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1138,7 +1138,7 @@ impl<T> Option<T> {
|
||||
/// Computes a default function result (if none), or
|
||||
/// applies a different function to the contained value (if any).
|
||||
///
|
||||
/// # Examples
|
||||
/// # Basic examples
|
||||
///
|
||||
/// ```
|
||||
/// let k = 21;
|
||||
@ -1149,6 +1149,25 @@ impl<T> Option<T> {
|
||||
/// let x: Option<&str> = None;
|
||||
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
|
||||
/// ```
|
||||
///
|
||||
/// # Handling a Result-based fallback
|
||||
///
|
||||
/// A somewhat common occurrence when dealing with optional values
|
||||
/// in combination with [`Result<T, E>`] is the case where one wants to invoke
|
||||
/// a fallible fallback if the option is not present. This example
|
||||
/// parses a command line argument (if present), or the contents of a file to
|
||||
/// an integer. However, unlike accessing the command line argument, reading
|
||||
/// the file is fallible, so it must be wrapped with `Ok`.
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// let v: u64 = std::env::args()
|
||||
/// .nth(1)
|
||||
/// .map_or_else(|| std::fs::read_to_string("/etc/someconfig.conf"), Ok)?
|
||||
/// .parse()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn map_or_else<U, D, F>(self, default: D, f: F) -> U
|
||||
|
@ -58,6 +58,7 @@ dependencies = [
|
||||
"once_cell",
|
||||
"opener",
|
||||
"pretty_assertions",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
@ -645,6 +646,12 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.160"
|
||||
|
@ -57,6 +57,7 @@ walkdir = "2"
|
||||
sysinfo = { version = "0.26.0", optional = true }
|
||||
clap = { version = "4.2.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
|
||||
clap_complete = "4.2.2"
|
||||
semver = "1.0.17"
|
||||
|
||||
# Solaris doesn't support flock() and thus fd-lock is not option now
|
||||
[target.'cfg(not(target_os = "solaris"))'.dependencies]
|
||||
|
@ -85,6 +85,10 @@ clean_crate_tree! {
|
||||
}
|
||||
|
||||
fn clean_default(build: &Build, all: bool) {
|
||||
if build.config.dry_run() {
|
||||
return;
|
||||
}
|
||||
|
||||
rm_rf("tmp".as_ref());
|
||||
|
||||
if all {
|
||||
|
@ -25,6 +25,7 @@ use crate::flags::{Color, Flags, Warnings};
|
||||
use crate::util::{exe, output, t};
|
||||
use build_helper::detail_exit_macro;
|
||||
use once_cell::sync::OnceCell;
|
||||
use semver::Version;
|
||||
use serde::{Deserialize, Deserializer};
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
@ -1114,10 +1115,14 @@ impl Config {
|
||||
config.out = crate::util::absolute(&config.out);
|
||||
}
|
||||
|
||||
config.initial_rustc = build.rustc.map(PathBuf::from).unwrap_or_else(|| {
|
||||
config.initial_rustc = if let Some(rustc) = build.rustc {
|
||||
config.check_build_rustc_version(&rustc);
|
||||
PathBuf::from(rustc)
|
||||
} else {
|
||||
config.download_beta_toolchain();
|
||||
config.out.join(config.build.triple).join("stage0/bin/rustc")
|
||||
});
|
||||
};
|
||||
|
||||
config.initial_cargo = build
|
||||
.cargo
|
||||
.map(|cargo| {
|
||||
@ -1779,6 +1784,42 @@ impl Config {
|
||||
self.rust_codegen_backends.get(0).cloned()
|
||||
}
|
||||
|
||||
pub fn check_build_rustc_version(&self, rustc_path: &str) {
|
||||
if self.dry_run() {
|
||||
return;
|
||||
}
|
||||
|
||||
// check rustc version is same or lower with 1 apart from the building one
|
||||
let mut cmd = Command::new(rustc_path);
|
||||
cmd.arg("--version");
|
||||
let rustc_output = output(&mut cmd)
|
||||
.lines()
|
||||
.next()
|
||||
.unwrap()
|
||||
.split(' ')
|
||||
.nth(1)
|
||||
.unwrap()
|
||||
.split('-')
|
||||
.next()
|
||||
.unwrap()
|
||||
.to_owned();
|
||||
let rustc_version = Version::parse(&rustc_output.trim()).unwrap();
|
||||
let source_version =
|
||||
Version::parse(&fs::read_to_string(self.src.join("src/version")).unwrap().trim())
|
||||
.unwrap();
|
||||
if !(source_version == rustc_version
|
||||
|| (source_version.major == rustc_version.major
|
||||
&& source_version.minor == rustc_version.minor + 1))
|
||||
{
|
||||
let prev_version = format!("{}.{}.x", source_version.major, source_version.minor - 1);
|
||||
eprintln!(
|
||||
"Unexpected rustc version: {}, we should use {}/{} to build source with {}",
|
||||
rustc_version, prev_version, source_version, source_version
|
||||
);
|
||||
detail_exit_macro!(1);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the commit to download, or `None` if we shouldn't download CI artifacts.
|
||||
fn download_ci_rustc_commit(&self, download_rustc: Option<StringOrBool>) -> Option<String> {
|
||||
// If `download-rustc` is not set, default to rebuilding.
|
||||
|
@ -31,6 +31,7 @@ static SETTINGS_HASHES: &[&str] = &[
|
||||
"ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8",
|
||||
"56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922",
|
||||
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
|
||||
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
|
||||
];
|
||||
static RUST_ANALYZER_SETTINGS: &str = include_str!("../etc/rust_analyzer_settings.json");
|
||||
|
||||
|
@ -7,7 +7,14 @@
|
||||
"check",
|
||||
"--json-output"
|
||||
],
|
||||
"rust-analyzer.linkedProjects": ["src/bootstrap/Cargo.toml", "Cargo.toml"],
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"Cargo.toml",
|
||||
"src/tools/x/Cargo.toml",
|
||||
"src/bootstrap/Cargo.toml",
|
||||
"src/tools/rust-analyzer/Cargo.toml",
|
||||
"compiler/rustc_codegen_cranelift/Cargo.toml",
|
||||
"compiler/rustc_codegen_gcc/Cargo.toml"
|
||||
],
|
||||
"rust-analyzer.rustfmt.overrideCommand": [
|
||||
"./build/host/rustfmt/bin/rustfmt",
|
||||
"--edition=2021"
|
||||
|
@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "x"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
|
@ -31,4 +31,4 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
|
||||
// Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
|
||||
// from the CHECK-NOT above. We don't check the attributes here because we can't rely
|
||||
// on all of them being set until LLVM 15.
|
||||
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
|
||||
// CHECK: declare {{(dso_local )?}}noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
|
||||
|
@ -28,6 +28,6 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
|
||||
|
||||
// Hide the `allocalign` attribute in the declaration of __rust_alloc
|
||||
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
|
||||
// CHECK: declare noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
|
||||
// CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
|
||||
|
||||
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
|
||||
// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) {{(uwtable )?}}"alloc-family"="__rust_alloc" {{.*}} }
|
||||
|
@ -6,7 +6,7 @@
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub fn test() {
|
||||
// CHECK: call noundef i8 @some_true(), !range [[R0:![0-9]+]]
|
||||
// CHECK: call noundef i8 @some_true(){{( #[0-9]+)?}}, !range [[R0:![0-9]+]]
|
||||
// CHECK: [[R0]] = !{i8 0, i8 3}
|
||||
some_true();
|
||||
}
|
||||
|
@ -6,11 +6,11 @@
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Column numbers are 1-based. Regression test for #65437.
|
||||
// CHECK: call void @giraffe(), !dbg [[A:!.*]]
|
||||
// CHECK: call void @giraffe(){{( #[0-9]+)?}}, !dbg [[A:!.*]]
|
||||
giraffe();
|
||||
|
||||
// Column numbers use byte offests. Regression test for #67360
|
||||
// CHECK: call void @turtle(), !dbg [[B:!.*]]
|
||||
// CHECK: call void @turtle(){{( #[0-9]+)?}}, !dbg [[B:!.*]]
|
||||
/* ż */ turtle();
|
||||
|
||||
// CHECK: [[A]] = !DILocation(line: 10, column: 9,
|
||||
|
@ -1,4 +1,5 @@
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
// needs-unwind - this test verifies the amount of drop calls when unwinding is used
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
@ -6,72 +6,72 @@
|
||||
// `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their
|
||||
// definitions
|
||||
|
||||
// CHECK: @A = local_unnamed_addr constant
|
||||
// CHECK: @A = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
static A: u8 = 0;
|
||||
|
||||
// CHECK: @B = local_unnamed_addr global
|
||||
// CHECK: @B = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
static mut B: u8 = 0;
|
||||
|
||||
// CHECK: @C = local_unnamed_addr constant
|
||||
// CHECK: @C = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
pub static C: u8 = 0;
|
||||
|
||||
// CHECK: @D = local_unnamed_addr global
|
||||
// CHECK: @D = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
pub static mut D: u8 = 0;
|
||||
|
||||
mod private {
|
||||
// CHECK: @E = local_unnamed_addr constant
|
||||
// CHECK: @E = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
static E: u8 = 0;
|
||||
|
||||
// CHECK: @F = local_unnamed_addr global
|
||||
// CHECK: @F = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
static mut F: u8 = 0;
|
||||
|
||||
// CHECK: @G = local_unnamed_addr constant
|
||||
// CHECK: @G = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
pub static G: u8 = 0;
|
||||
|
||||
// CHECK: @H = local_unnamed_addr global
|
||||
// CHECK: @H = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
pub static mut H: u8 = 0;
|
||||
}
|
||||
|
||||
const HIDDEN: () = {
|
||||
// CHECK: @I = local_unnamed_addr constant
|
||||
// CHECK: @I = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
static I: u8 = 0;
|
||||
|
||||
// CHECK: @J = local_unnamed_addr global
|
||||
// CHECK: @J = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
static mut J: u8 = 0;
|
||||
|
||||
// CHECK: @K = local_unnamed_addr constant
|
||||
// CHECK: @K = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
pub static K: u8 = 0;
|
||||
|
||||
// CHECK: @L = local_unnamed_addr global
|
||||
// CHECK: @L = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
pub static mut L: u8 = 0;
|
||||
};
|
||||
|
||||
fn x() {
|
||||
// CHECK: @M = local_unnamed_addr constant
|
||||
// CHECK: @M = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
static M: fn() = x;
|
||||
|
||||
// CHECK: @N = local_unnamed_addr global
|
||||
// CHECK: @N = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
static mut N: u8 = 0;
|
||||
|
||||
// CHECK: @O = local_unnamed_addr constant
|
||||
// CHECK: @O = {{(dso_local )?}}local_unnamed_addr constant
|
||||
#[no_mangle]
|
||||
pub static O: u8 = 0;
|
||||
|
||||
// CHECK: @P = local_unnamed_addr global
|
||||
// CHECK: @P = {{(dso_local )?}}local_unnamed_addr global
|
||||
#[no_mangle]
|
||||
pub static mut P: u8 = 0;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// CHECK-LABEL: define void @string_new
|
||||
// CHECK-LABEL: define {{(dso_local )?}}void @string_new
|
||||
#[no_mangle]
|
||||
pub fn string_new() -> String {
|
||||
// CHECK: store ptr inttoptr
|
||||
@ -17,7 +17,7 @@ pub fn string_new() -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define void @empty_to_string
|
||||
// CHECK-LABEL: define {{(dso_local )?}}void @empty_to_string
|
||||
#[no_mangle]
|
||||
pub fn empty_to_string() -> String {
|
||||
// CHECK: store ptr inttoptr
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
// CHECK: @VAR1 = constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
|
||||
// CHECK: @VAR1 = {{(dso_local )?}}constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
|
||||
#[no_mangle]
|
||||
#[link_section = ".test_one"]
|
||||
#[cfg(target_endian = "little")]
|
||||
@ -19,17 +19,17 @@ pub enum E {
|
||||
B(f32)
|
||||
}
|
||||
|
||||
// CHECK: @VAR2 = constant {{.*}}, section ".test_two"
|
||||
// CHECK: @VAR2 = {{(dso_local )?}}constant {{.*}}, section ".test_two"
|
||||
#[no_mangle]
|
||||
#[link_section = ".test_two"]
|
||||
pub static VAR2: E = E::A(666);
|
||||
|
||||
// CHECK: @VAR3 = constant {{.*}}, section ".test_three"
|
||||
// CHECK: @VAR3 = {{(dso_local )?}}constant {{.*}}, section ".test_three"
|
||||
#[no_mangle]
|
||||
#[link_section = ".test_three"]
|
||||
pub static VAR3: E = E::B(1.);
|
||||
|
||||
// CHECK: define void @fn1() {{.*}} section ".test_four" {
|
||||
// CHECK: define {{(dso_local )?}}void @fn1() {{.*}} section ".test_four" {
|
||||
#[no_mangle]
|
||||
#[link_section = ".test_four"]
|
||||
pub fn fn1() {}
|
||||
|
@ -19,7 +19,7 @@ pub fn example() {
|
||||
}
|
||||
|
||||
// CHECK-LABEL: @example
|
||||
// CHECK: tail call void @bar(), !dbg [[DBG_ID:![0-9]+]]
|
||||
// CHECK: tail call void @bar(){{( #[0-9]+)?}}, !dbg [[DBG_ID:![0-9]+]]
|
||||
// CHECK: [[DBG_ID]] = !DILocation(line: 7,
|
||||
// CHECK-SAME: inlinedAt: [[INLINE_ID:![0-9]+]])
|
||||
// CHECK: [[INLINE_ID]] = !DILocation(line: 18,
|
||||
|
@ -12,7 +12,7 @@ use std::arch::asm;
|
||||
pub unsafe extern "C" fn f() {
|
||||
// Check that f has naked and noinline attributes.
|
||||
//
|
||||
// CHECK: define void @f() unnamed_addr [[ATTR:#[0-9]+]]
|
||||
// CHECK: define {{(dso_local )?}}void @f() unnamed_addr [[ATTR:#[0-9]+]]
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: call void asm
|
||||
asm!("", options(noreturn));
|
||||
@ -22,7 +22,7 @@ pub unsafe extern "C" fn f() {
|
||||
pub unsafe fn g() {
|
||||
// Check that call to f is not inlined.
|
||||
//
|
||||
// CHECK-LABEL: define void @g()
|
||||
// CHECK-LABEL: define {{(dso_local )?}}void @g()
|
||||
// CHECK-NEXT: start:
|
||||
// CHECK-NEXT: call void @f()
|
||||
f();
|
||||
|
@ -1,5 +1,6 @@
|
||||
// ignore-msvc
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
// needs-unwind
|
||||
|
||||
// compile-flags: -O -C no-prepopulate-passes
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
// CHECK-LABEL: define noundef i8 @copy_byte(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @copy_byte(
|
||||
#[no_mangle]
|
||||
pub unsafe fn copy_byte(p: *const u8) -> u8 {
|
||||
// CHECK-NOT: load
|
||||
@ -19,7 +19,7 @@ pub unsafe fn copy_byte(p: *const u8) -> u8 {
|
||||
*p
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define noundef i8 @read_byte(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @read_byte(
|
||||
#[no_mangle]
|
||||
pub unsafe fn read_byte(p: *const u8) -> u8 {
|
||||
// CHECK-NOT: load
|
||||
@ -29,7 +29,7 @@ pub unsafe fn read_byte(p: *const u8) -> u8 {
|
||||
p.read()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define i8 @read_byte_maybe_uninit(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}i8 @read_byte_maybe_uninit(
|
||||
#[no_mangle]
|
||||
pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u8> {
|
||||
// CHECK-NOT: load
|
||||
@ -39,7 +39,7 @@ pub unsafe fn read_byte_maybe_uninit(p: *const MaybeUninit<u8>) -> MaybeUninit<u
|
||||
p.read()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define noundef i8 @read_byte_assume_init(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}noundef i8 @read_byte_assume_init(
|
||||
#[no_mangle]
|
||||
pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
|
||||
// CHECK-NOT: load
|
||||
@ -49,7 +49,7 @@ pub unsafe fn read_byte_assume_init(p: &MaybeUninit<u8>) -> u8 {
|
||||
p.assume_init_read()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define noundef i32 @copy_char(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @copy_char(
|
||||
#[no_mangle]
|
||||
pub unsafe fn copy_char(p: *const char) -> char {
|
||||
// CHECK-NOT: load
|
||||
@ -60,7 +60,7 @@ pub unsafe fn copy_char(p: *const char) -> char {
|
||||
*p
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define noundef i32 @read_char(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char(
|
||||
#[no_mangle]
|
||||
pub unsafe fn read_char(p: *const char) -> char {
|
||||
// CHECK-NOT: load
|
||||
@ -71,7 +71,7 @@ pub unsafe fn read_char(p: *const char) -> char {
|
||||
p.read()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define i32 @read_char_maybe_uninit(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}i32 @read_char_maybe_uninit(
|
||||
#[no_mangle]
|
||||
pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit<char> {
|
||||
// CHECK-NOT: load
|
||||
@ -82,7 +82,7 @@ pub unsafe fn read_char_maybe_uninit(p: *const MaybeUninit<char>) -> MaybeUninit
|
||||
p.read()
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define noundef i32 @read_char_assume_init(
|
||||
// CHECK-LABEL: define {{(dso_local )?}}noundef i32 @read_char_assume_init(
|
||||
#[no_mangle]
|
||||
pub unsafe fn read_char_assume_init(p: &MaybeUninit<char>) -> char {
|
||||
// CHECK-NOT: load
|
||||
|
@ -6,31 +6,31 @@
|
||||
#![crate_type="lib"]
|
||||
|
||||
type ScalarZstLast = (u128, ());
|
||||
// CHECK: define i128 @test_ScalarZstLast(i128 %_1)
|
||||
// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstLast(i128 %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast { loop {} }
|
||||
|
||||
type ScalarZstFirst = ((), u128);
|
||||
// CHECK: define i128 @test_ScalarZstFirst(i128 %_1)
|
||||
// CHECK: define {{(dso_local )?}}i128 @test_ScalarZstFirst(i128 %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { loop {} }
|
||||
|
||||
type ScalarPairZstLast = (u8, u128, ());
|
||||
// CHECK: define { i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
|
||||
// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1)
|
||||
#[no_mangle]
|
||||
pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast { loop {} }
|
||||
|
||||
type ScalarPairZstFirst = ((), u8, u128);
|
||||
// CHECK: define { i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
|
||||
// CHECK: define {{(dso_local )?}}{ i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1)
|
||||
#[no_mangle]
|
||||
pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst { loop {} }
|
||||
|
||||
type ScalarPairLotsOfZsts = ((), u8, (), u128, ());
|
||||
// CHECK: define { i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
|
||||
// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1)
|
||||
#[no_mangle]
|
||||
pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts { loop {} }
|
||||
|
||||
type ScalarPairLottaNesting = (((), ((), u8, (), u128, ())), ());
|
||||
// CHECK: define { i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
|
||||
// CHECK: define {{(dso_local )?}}{ i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1)
|
||||
#[no_mangle]
|
||||
pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting { loop {} }
|
||||
|
@ -17,60 +17,60 @@ pub struct i64x4(i64, i64, i64, i64);
|
||||
#[derive(Copy, Clone)]
|
||||
pub union UnionI64x4{ a:(), b: i64x4 }
|
||||
|
||||
// CHECK: define void @test_UnionI64x4({{<4 x i64>\*|ptr}} {{.*}} %_1)
|
||||
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4({{<4 x i64>\*|ptr}} {{.*}} %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionI64x4(_: UnionI64x4) { loop {} }
|
||||
|
||||
pub union UnionI64x4_{ a: i64x4, b: (), c:i64x4, d: Unhab, e: ((),()), f: UnionI64x4 }
|
||||
|
||||
// CHECK: define void @test_UnionI64x4_({{<4 x i64>\*|ptr}} {{.*}} %_1)
|
||||
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4_({{<4 x i64>\*|ptr}} {{.*}} %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionI64x4_(_: UnionI64x4_) { loop {} }
|
||||
|
||||
pub union UnionI64x4I64{ a: i64x4, b: i64 }
|
||||
|
||||
// CHECK: define void @test_UnionI64x4I64({{%UnionI64x4I64\*|ptr}} {{.*}} %_1)
|
||||
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4I64({{%UnionI64x4I64\*|ptr}} {{.*}} %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionI64x4I64(_: UnionI64x4I64) { loop {} }
|
||||
|
||||
pub union UnionI64x4Tuple{ a: i64x4, b: (i64, i64, i64, i64) }
|
||||
|
||||
// CHECK: define void @test_UnionI64x4Tuple({{%UnionI64x4Tuple\*|ptr}} {{.*}} %_1)
|
||||
// CHECK: define {{(dso_local )?}}void @test_UnionI64x4Tuple({{%UnionI64x4Tuple\*|ptr}} {{.*}} %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionI64x4Tuple(_: UnionI64x4Tuple) { loop {} }
|
||||
|
||||
|
||||
pub union UnionF32{a:f32}
|
||||
|
||||
// CHECK: define float @test_UnionF32(float %_1)
|
||||
// CHECK: define {{(dso_local )?}}float @test_UnionF32(float %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionF32(_: UnionF32) -> UnionF32 { loop {} }
|
||||
|
||||
pub union UnionF32F32{a:f32, b:f32}
|
||||
|
||||
// CHECK: define float @test_UnionF32F32(float %_1)
|
||||
// CHECK: define {{(dso_local )?}}float @test_UnionF32F32(float %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionF32F32(_: UnionF32F32) -> UnionF32F32 { loop {} }
|
||||
|
||||
pub union UnionF32U32{a:f32, b:u32}
|
||||
|
||||
// CHECK: define i32 @test_UnionF32U32(i32{{( %0)?}})
|
||||
// CHECK: define {{(dso_local )?}}i32 @test_UnionF32U32(i32{{( %0)?}})
|
||||
#[no_mangle]
|
||||
pub fn test_UnionF32U32(_: UnionF32U32) -> UnionF32U32 { loop {} }
|
||||
|
||||
pub union UnionU128{a:u128}
|
||||
// CHECK: define i128 @test_UnionU128(i128 %_1)
|
||||
// CHECK: define {{(dso_local )?}}i128 @test_UnionU128(i128 %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionU128(_: UnionU128) -> UnionU128 { loop {} }
|
||||
|
||||
#[repr(C)]
|
||||
pub union CUnionU128{a:u128}
|
||||
// CHECK: define void @test_CUnionU128({{%CUnionU128\*|ptr}} {{.*}} %_1)
|
||||
// CHECK: define {{(dso_local )?}}void @test_CUnionU128({{%CUnionU128\*|ptr}} {{.*}} %_1)
|
||||
#[no_mangle]
|
||||
pub fn test_CUnionU128(_: CUnionU128) { loop {} }
|
||||
|
||||
pub union UnionBool { b:bool }
|
||||
// CHECK: define noundef zeroext i1 @test_UnionBool(i8 %b)
|
||||
// CHECK: define {{(dso_local )?}}noundef zeroext i1 @test_UnionBool(i8 %b)
|
||||
#[no_mangle]
|
||||
pub fn test_UnionBool(b: UnionBool) -> bool { unsafe { b.b } }
|
||||
// CHECK: %0 = trunc i8 %b to i1
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: -C opt-level=0
|
||||
// needs-unwind
|
||||
|
||||
// Test that `nounwind` attributes are correctly applied to exported `C` and `C-unwind` extern
|
||||
// functions. `C-unwind` functions MUST NOT have this attribute. We disable optimizations above
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: -C opt-level=0
|
||||
// needs-unwind
|
||||
|
||||
// Test that `nounwind` attributes are correctly applied to exported `cdecl` and
|
||||
// `cdecl-unwind` extern functions. `cdecl-unwind` functions MUST NOT have this attribute. We
|
||||
|
@ -1,5 +1,6 @@
|
||||
// compile-flags: -C opt-level=0
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
// needs-unwind
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: -C opt-level=0
|
||||
// needs-unwind
|
||||
|
||||
// Test that `nounwind` attributes are correctly applied to exported `system` and `system-unwind`
|
||||
// extern functions. `system-unwind` functions MUST NOT have this attribute. We disable
|
||||
|
@ -1,5 +1,6 @@
|
||||
// compile-flags: -C opt-level=0
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
// needs-unwind
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(c_unwind)]
|
||||
|
@ -1,5 +1,6 @@
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
// ignore-wasm32-bare compiled with panic=abort by default
|
||||
// needs-unwind
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(c_unwind)]
|
||||
|
@ -5,6 +5,7 @@
|
||||
// [new]min-llvm-version: 17
|
||||
// compile-flags: -O
|
||||
// ignore-debug: the debug assertions get in the way
|
||||
// needs-unwind
|
||||
#![crate_type = "lib"]
|
||||
#![feature(shrink_to)]
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
fn produces_string() -> Option<String> {
|
||||
Some("my cool string".to_owned())
|
||||
}
|
||||
|
||||
fn takes_str_but_too_many_refs(_: &&str) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn no_args() -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn generic_ref<T>(_: &T) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
extern "C" fn takes_str_but_wrong_abi(_: &str) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
unsafe fn takes_str_but_unsafe(_: &str) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
struct TypeWithoutDeref;
|
||||
|
||||
fn main() {
|
||||
let _ = produces_string().and_then(takes_str_but_too_many_refs);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
let _ = produces_string().and_then(takes_str_but_wrong_abi);
|
||||
//~^ ERROR expected a `FnOnce<(String,)>` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
|
||||
let _ = produces_string().and_then(takes_str_but_unsafe);
|
||||
//~^ ERROR expected a `FnOnce<(String,)>` closure, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
|
||||
let _ = produces_string().and_then(no_args);
|
||||
//~^ ERROR function is expected to take 1 argument, but it takes 0 arguments
|
||||
let _ = produces_string().and_then(generic_ref);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/suggest-option-asderef-unfixable.rs:28:40
|
||||
|
|
||||
LL | fn takes_str_but_too_many_refs(_: &&str) -> Option<()> {
|
||||
| ------------------------------------------------------ found signature defined here
|
||||
...
|
||||
LL | let _ = produces_string().and_then(takes_str_but_too_many_refs);
|
||||
| -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected due to this
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected function signature `fn(String) -> _`
|
||||
found function signature `for<'a, 'b> fn(&'a &'b str) -> _`
|
||||
note: required by a bound in `Option::<T>::and_then`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error[E0277]: expected a `FnOnce<(String,)>` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
|
||||
--> $DIR/suggest-option-asderef-unfixable.rs:30:40
|
||||
|
|
||||
LL | let _ = produces_string().and_then(takes_str_but_wrong_abi);
|
||||
| -------- ^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(String,)>` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `FnOnce<(String,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}`
|
||||
note: required by a bound in `Option::<T>::and_then`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error[E0277]: expected a `FnOnce<(String,)>` closure, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
|
||||
--> $DIR/suggest-option-asderef-unfixable.rs:32:40
|
||||
|
|
||||
LL | let _ = produces_string().and_then(takes_str_but_unsafe);
|
||||
| -------- ^^^^^^^^^^^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `FnOnce<(String,)>` is not implemented for fn item `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
note: required by a bound in `Option::<T>::and_then`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error[E0593]: function is expected to take 1 argument, but it takes 0 arguments
|
||||
--> $DIR/suggest-option-asderef-unfixable.rs:34:40
|
||||
|
|
||||
LL | fn no_args() -> Option<()> {
|
||||
| -------------------------- takes 0 arguments
|
||||
...
|
||||
LL | let _ = produces_string().and_then(no_args);
|
||||
| -------- ^^^^^^^ expected function that takes 1 argument
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `Option::<T>::and_then`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/suggest-option-asderef-unfixable.rs:36:40
|
||||
|
|
||||
LL | fn generic_ref<T>(_: &T) -> Option<()> {
|
||||
| -------------------------------------- found signature defined here
|
||||
...
|
||||
LL | let _ = produces_string().and_then(generic_ref);
|
||||
| -------- ^^^^^^^^^^^ expected due to this
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected function signature `fn(String) -> _`
|
||||
found function signature `for<'a> fn(&'a _) -> _`
|
||||
note: required by a bound in `Option::<T>::and_then`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: do not borrow the argument
|
||||
|
|
||||
LL - fn generic_ref<T>(_: &T) -> Option<()> {
|
||||
LL + fn generic_ref<T>(_: T) -> Option<()> {
|
||||
|
|
||||
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/suggest-option-asderef-unfixable.rs:38:45
|
||||
|
|
||||
LL | fn takes_str_but_too_many_refs(_: &&str) -> Option<()> {
|
||||
| ------------------------------------------------------ found signature defined here
|
||||
...
|
||||
LL | let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs);
|
||||
| -------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected due to this
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected function signature `fn(TypeWithoutDeref) -> _`
|
||||
found function signature `for<'a, 'b> fn(&'a &'b str) -> _`
|
||||
note: required by a bound in `Option::<T>::and_then`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0593, E0631.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
30
tests/ui/mismatched_types/suggest-option-asderef.fixed
Normal file
30
tests/ui/mismatched_types/suggest-option-asderef.fixed
Normal file
@ -0,0 +1,30 @@
|
||||
// run-rustfix
|
||||
|
||||
fn produces_string() -> Option<String> {
|
||||
Some("my cool string".to_owned())
|
||||
}
|
||||
|
||||
fn takes_str(_: &str) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn takes_str_mut(_: &mut str) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn generic<T>(_: T) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: Option<()> = produces_string().as_deref().and_then(takes_str);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| HELP call `Option::as_deref()` first
|
||||
let _: Option<Option<()>> = produces_string().as_deref().map(takes_str);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| HELP call `Option::as_deref()` first
|
||||
let _: Option<Option<()>> = produces_string().as_deref_mut().map(takes_str_mut);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| HELP call `Option::as_deref_mut()` first
|
||||
let _ = produces_string().and_then(generic);
|
||||
}
|
30
tests/ui/mismatched_types/suggest-option-asderef.rs
Normal file
30
tests/ui/mismatched_types/suggest-option-asderef.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// run-rustfix
|
||||
|
||||
fn produces_string() -> Option<String> {
|
||||
Some("my cool string".to_owned())
|
||||
}
|
||||
|
||||
fn takes_str(_: &str) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn takes_str_mut(_: &mut str) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn generic<T>(_: T) -> Option<()> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _: Option<()> = produces_string().and_then(takes_str);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| HELP call `Option::as_deref()` first
|
||||
let _: Option<Option<()>> = produces_string().map(takes_str);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| HELP call `Option::as_deref()` first
|
||||
let _: Option<Option<()>> = produces_string().map(takes_str_mut);
|
||||
//~^ ERROR type mismatch in function arguments
|
||||
//~| HELP call `Option::as_deref_mut()` first
|
||||
let _ = produces_string().and_then(generic);
|
||||
}
|
63
tests/ui/mismatched_types/suggest-option-asderef.stderr
Normal file
63
tests/ui/mismatched_types/suggest-option-asderef.stderr
Normal file
@ -0,0 +1,63 @@
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/suggest-option-asderef.rs:20:52
|
||||
|
|
||||
LL | fn takes_str(_: &str) -> Option<()> {
|
||||
| ----------------------------------- found signature defined here
|
||||
...
|
||||
LL | let _: Option<()> = produces_string().and_then(takes_str);
|
||||
| -------- ^^^^^^^^^ expected due to this
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected function signature `fn(String) -> _`
|
||||
found function signature `for<'a> fn(&'a str) -> _`
|
||||
note: required by a bound in `Option::<T>::and_then`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: call `Option::as_deref()` first
|
||||
|
|
||||
LL | let _: Option<()> = produces_string().as_deref().and_then(takes_str);
|
||||
| +++++++++++
|
||||
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/suggest-option-asderef.rs:23:55
|
||||
|
|
||||
LL | fn takes_str(_: &str) -> Option<()> {
|
||||
| ----------------------------------- found signature defined here
|
||||
...
|
||||
LL | let _: Option<Option<()>> = produces_string().map(takes_str);
|
||||
| --- ^^^^^^^^^ expected due to this
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected function signature `fn(String) -> _`
|
||||
found function signature `for<'a> fn(&'a str) -> _`
|
||||
note: required by a bound in `Option::<T>::map`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: call `Option::as_deref()` first
|
||||
|
|
||||
LL | let _: Option<Option<()>> = produces_string().as_deref().map(takes_str);
|
||||
| +++++++++++
|
||||
|
||||
error[E0631]: type mismatch in function arguments
|
||||
--> $DIR/suggest-option-asderef.rs:26:55
|
||||
|
|
||||
LL | fn takes_str_mut(_: &mut str) -> Option<()> {
|
||||
| ------------------------------------------- found signature defined here
|
||||
...
|
||||
LL | let _: Option<Option<()>> = produces_string().map(takes_str_mut);
|
||||
| --- ^^^^^^^^^^^^^ expected due to this
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected function signature `fn(String) -> _`
|
||||
found function signature `for<'a> fn(&'a mut str) -> _`
|
||||
note: required by a bound in `Option::<T>::map`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: call `Option::as_deref_mut()` first
|
||||
|
|
||||
LL | let _: Option<Option<()>> = produces_string().as_deref_mut().map(takes_str_mut);
|
||||
| +++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0631`.
|
11
tests/ui/typeck/return-dyn-type-mismatch-2.rs
Normal file
11
tests/ui/typeck/return-dyn-type-mismatch-2.rs
Normal file
@ -0,0 +1,11 @@
|
||||
trait Trait<T> {}
|
||||
|
||||
fn foo<T>() -> dyn Trait<T>
|
||||
where
|
||||
dyn Trait<T>: Sized, // pesky sized predicate
|
||||
{
|
||||
42
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
15
tests/ui/typeck/return-dyn-type-mismatch-2.stderr
Normal file
15
tests/ui/typeck/return-dyn-type-mismatch-2.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/return-dyn-type-mismatch-2.rs:7:5
|
||||
|
|
||||
LL | fn foo<T>() -> dyn Trait<T>
|
||||
| ------------ expected `(dyn Trait<T> + 'static)` because of return type
|
||||
...
|
||||
LL | 42
|
||||
| ^^ expected `dyn Trait`, found integer
|
||||
|
|
||||
= note: expected trait object `(dyn Trait<T> + 'static)`
|
||||
found type `{integer}`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
21
tests/ui/typeck/return-dyn-type-mismatch.rs
Normal file
21
tests/ui/typeck/return-dyn-type-mismatch.rs
Normal file
@ -0,0 +1,21 @@
|
||||
pub trait TestTrait {
|
||||
type MyType;
|
||||
|
||||
fn func() -> Option<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
impl<T> dyn TestTrait<MyType = T>
|
||||
where
|
||||
Self: Sized, // pesky sized predicate
|
||||
{
|
||||
fn other_func() -> dyn TestTrait<MyType = T> {
|
||||
match Self::func() {
|
||||
None => None,
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
15
tests/ui/typeck/return-dyn-type-mismatch.stderr
Normal file
15
tests/ui/typeck/return-dyn-type-mismatch.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/return-dyn-type-mismatch.rs:15:21
|
||||
|
|
||||
LL | fn other_func() -> dyn TestTrait<MyType = T> {
|
||||
| ------------------------- expected `(dyn TestTrait<MyType = T> + 'static)` because of return type
|
||||
LL | match Self::func() {
|
||||
LL | None => None,
|
||||
| ^^^^ expected `dyn TestTrait`, found `Option<_>`
|
||||
|
|
||||
= note: expected trait object `(dyn TestTrait<MyType = T> + 'static)`
|
||||
found enum `Option<_>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
x
Reference in New Issue
Block a user