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 6 pull requests #121692

Closed
wants to merge 15 commits into from
Closed
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
63 changes: 41 additions & 22 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
@@ -390,20 +390,21 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[

// Entry point:
gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)),
ungated!(start, Normal, template!(Word), WarnFollowing),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
ungated!(start, Normal, template!(Word), WarnFollowing, @only_local: true),
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, @only_local: true),
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, @only_local: true),

// Modules, prelude, and resolution:
ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing),
ungated!(no_std, CrateLevel, template!(Word), WarnFollowing),
ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing),
ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing, @only_local: true),
ungated!(no_std, CrateLevel, template!(Word), WarnFollowing, @only_local: true),
ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing, @only_local: true),
ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing),

// Runtime
ungated!(
windows_subsystem, CrateLevel,
template!(NameValueStr: "windows|console"), FutureWarnFollowing
template!(NameValueStr: "windows|console"), FutureWarnFollowing,
@only_local: true
),
ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070

@@ -416,13 +417,17 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
DuplicatesOk, @only_local: true,
),
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding),
ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding, @only_local: true),
gated!(
no_sanitize, Normal,
template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
experimental!(no_sanitize)
@only_local: true, experimental!(no_sanitize)
),
gated!(
coverage, Normal, template!(Word, List: "on|off"),
WarnFollowing, @only_local: true,
coverage_attribute, experimental!(coverage)
),
gated!(coverage, Normal, template!(Word, List: "on|off"), WarnFollowing, coverage_attribute, experimental!(coverage)),

ungated!(
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk
@@ -431,7 +436,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// Debugging
ungated!(
debugger_visualizer, Normal,
template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), DuplicatesOk
template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
DuplicatesOk, @only_local: true
),

// ==========================================================================
@@ -455,26 +461,35 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
marker_trait_attr, experimental!(marker)
),
gated!(
thread_local, Normal, template!(Word), WarnFollowing,
thread_local, Normal, template!(Word), WarnFollowing, @only_local: true,
"`#[thread_local]` is an experimental feature, and does not currently handle destructors",
),
gated!(no_core, CrateLevel, template!(Word), WarnFollowing, experimental!(no_core)),
gated!(
no_core, CrateLevel, template!(Word), WarnFollowing,
@only_local: true, experimental!(no_core)
),
// RFC 2412
gated!(
optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute,
experimental!(optimize),
optimize, Normal, template!(List: "size|speed"), ErrorPreceding,
@only_local: true, optimize_attribute, experimental!(optimize)
),

gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)),
gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)),
gated!(
ffi_pure, Normal, template!(Word), WarnFollowing,
@only_local: true, experimental!(ffi_pure)
),
gated!(
ffi_const, Normal, template!(Word), WarnFollowing,
@only_local: true, experimental!(ffi_const)
),
gated!(
register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk,
experimental!(register_tool),
@only_local: true, experimental!(register_tool),
),

gated!(
cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing,
experimental!(cmse_nonsecure_entry)
@only_local: true, experimental!(cmse_nonsecure_entry)
),
// RFC 2632
gated!(
@@ -492,11 +507,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// `#[collapse_debuginfo]`
gated!(
collapse_debuginfo, Normal, template!(Word, List: "no|external|yes"), ErrorFollowing,
experimental!(collapse_debuginfo)
@only_local: true, experimental!(collapse_debuginfo)
),

// RFC 2397
gated!(do_not_recommend, Normal, template!(Word), WarnFollowing, experimental!(do_not_recommend)),
gated!(
do_not_recommend, Normal, template!(Word), WarnFollowing,
@only_local: true, experimental!(do_not_recommend)
),

// `#[cfi_encoding = ""]`
gated!(
@@ -528,7 +546,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
ungated!(
rustc_default_body_unstable, Normal,
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
DuplicatesOk, @only_local: true
),
gated!(
allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
83 changes: 1 addition & 82 deletions compiler/rustc_lint/src/internal.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
use crate::lints::{
BadOptAccessDiag, DefaultHashTypesDiag, DiagOutOfImpl, LintPassByHand, NonExistentDocKeyword,
QueryInstability, SpanUseEqCtxtDiag, TyQualified, TykindDiag, TykindKind, UntranslatableDiag,
UntranslatableDiagnosticTrivial,
};
use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_ast as ast;
@@ -361,15 +360,7 @@ declare_tool_lint! {
report_in_external_macro: true
}

declare_tool_lint! {
/// The `untranslatable_diagnostic_trivial` lint detects diagnostics created using only static strings.
pub rustc::UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL,
Deny,
"prevent creation of diagnostics which cannot be translated, which use only static strings",
report_in_external_macro: true
}

declare_lint_pass!(Diagnostics => [ UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL, UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL ]);
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);

impl LateLintPass<'_> for Diagnostics {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
@@ -425,78 +416,6 @@ impl LateLintPass<'_> for Diagnostics {
}
}

impl EarlyLintPass for Diagnostics {
#[allow(unused_must_use)]
fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
// Looking for a straight chain of method calls from 'struct_span_err' to 'emit'.
let ast::StmtKind::Semi(expr) = &stmt.kind else {
return;
};
let ast::ExprKind::MethodCall(meth) = &expr.kind else {
return;
};
if meth.seg.ident.name != sym::emit || !meth.args.is_empty() {
return;
}
let mut segments = vec![];
let mut cur = &meth.receiver;
let fake = &[].into();
loop {
match &cur.kind {
ast::ExprKind::Call(func, args) => {
if let ast::ExprKind::Path(_, path) = &func.kind {
segments.push((path.segments.last().unwrap().ident.name, args))
}
break;
}
ast::ExprKind::MethodCall(method) => {
segments.push((method.seg.ident.name, &method.args));
cur = &method.receiver;
}
ast::ExprKind::MacCall(mac) => {
segments.push((mac.path.segments.last().unwrap().ident.name, fake));
break;
}
_ => {
break;
}
}
}
segments.reverse();
if segments.is_empty() {
return;
}
if segments[0].0.as_str() != "struct_span_err" {
return;
}
if !segments.iter().all(|(name, args)| {
let arg = match name.as_str() {
"struct_span_err" | "span_note" | "span_label" | "span_help" if args.len() == 2 => {
&args[1]
}
"note" | "help" if args.len() == 1 => &args[0],
_ => {
return false;
}
};
if let ast::ExprKind::Lit(lit) = arg.kind
&& let ast::token::LitKind::Str = lit.kind
{
true
} else {
false
}
}) {
return;
}
cx.emit_span_lint(
UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL,
stmt.span,
UntranslatableDiagnosticTrivial,
);
}
}

declare_tool_lint! {
/// The `bad_opt_access` lint detects accessing options by field instead of
/// the wrapper function.
1 change: 0 additions & 1 deletion compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
@@ -550,7 +550,6 @@ fn register_internals(store: &mut LintStore) {
store.register_lints(&TyTyKind::get_lints());
store.register_late_mod_pass(|_| Box::new(TyTyKind));
store.register_lints(&Diagnostics::get_lints());
store.register_early_pass(|| Box::new(Diagnostics));
store.register_late_mod_pass(|_| Box::new(Diagnostics));
store.register_lints(&BadOptAccess::get_lints());
store.register_late_mod_pass(|_| Box::new(BadOptAccess));
4 changes: 0 additions & 4 deletions compiler/rustc_lint/src/lints.rs
Original file line number Diff line number Diff line change
@@ -923,10 +923,6 @@ pub struct DiagOutOfImpl;
#[diag(lint_untranslatable_diag)]
pub struct UntranslatableDiag;

#[derive(LintDiagnostic)]
#[diag(lint_trivial_untranslatable_diag)]
pub struct UntranslatableDiagnosticTrivial;

#[derive(LintDiagnostic)]
#[diag(lint_bad_opt_access)]
pub struct BadOptAccessDiag<'a> {
12 changes: 11 additions & 1 deletion compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1294,10 +1294,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mut path_segments = path_segments.clone();
path_segments.push(ast::PathSegment::from_ident(ident));

let alias_import = if let NameBindingKind::Import { import, .. } =
name_binding.kind
&& let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
&& import.parent_scope.expansion == parent_scope.expansion
{
true
} else {
false
};

let is_extern_crate_that_also_appears_in_prelude =
name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();

if !is_extern_crate_that_also_appears_in_prelude {
if !is_extern_crate_that_also_appears_in_prelude || alias_import {
// add the module to the lookup
if seen_modules.insert(module.def_id()) {
if via_import { &mut worklist_via_import } else { &mut worklist }
4 changes: 3 additions & 1 deletion library/std/src/ffi/mod.rs
Original file line number Diff line number Diff line change
@@ -169,6 +169,7 @@ pub use core::ffi::FromBytesUntilNulError;
pub use core::ffi::{CStr, FromBytesWithNulError};

#[stable(feature = "rust1", since = "1.0.0")]
#[doc(inline)]
pub use self::os_str::{OsStr, OsString};

#[stable(feature = "core_ffi_c", since = "1.64.0")]
@@ -188,4 +189,5 @@ pub use core::ffi::c_void;
)]
pub use core::ffi::{VaList, VaListImpl};

mod os_str;
#[unstable(feature = "os_str_display", issue = "120048")]
pub mod os_str;
67 changes: 64 additions & 3 deletions library/std/src/ffi/os_str.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! The [`OsStr`] and [`OsString`] types and associated utilities.

#[cfg(test)]
mod tests;

@@ -1147,6 +1149,32 @@ impl OsStr {
pub fn eq_ignore_ascii_case<S: AsRef<OsStr>>(&self, other: S) -> bool {
self.inner.eq_ignore_ascii_case(&other.as_ref().inner)
}

/// Returns an object that implements [`Display`] for safely printing an
/// [`OsStr`] that may contain non-Unicode data. This may perform lossy
/// conversion, depending on the platform. If you would like an
/// implementation which escapes the [`OsStr`] please use [`Debug`]
/// instead.
///
/// [`Display`]: fmt::Display
/// [`Debug`]: fmt::Debug
///
/// # Examples
///
/// ```
/// #![feature(os_str_display)]
/// use std::ffi::OsStr;
///
/// let s = OsStr::new("Hello, world!");
/// println!("{}", s.display());
/// ```
#[unstable(feature = "os_str_display", issue = "120048")]
#[must_use = "this does not display the `OsStr`; \
it returns an object that can be displayed"]
#[inline]
pub fn display(&self) -> Display<'_> {
Display { os_str: self }
}
}

#[stable(feature = "box_from_os_str", since = "1.17.0")]
@@ -1441,9 +1469,42 @@ impl fmt::Debug for OsStr {
}
}

impl OsStr {
pub(crate) fn display(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.inner, formatter)
/// Helper struct for safely printing an [`OsStr`] with [`format!`] and `{}`.
///
/// An [`OsStr`] might contain non-Unicode data. This `struct` implements the
/// [`Display`] trait in a way that mitigates that. It is created by the
/// [`display`](OsStr::display) method on [`OsStr`]. This may perform lossy
/// conversion, depending on the platform. If you would like an implementation
/// which escapes the [`OsStr`] please use [`Debug`] instead.
///
/// # Examples
///
/// ```
/// #![feature(os_str_display)]
/// use std::ffi::OsStr;
///
/// let s = OsStr::new("Hello, world!");
/// println!("{}", s.display());
/// ```
///
/// [`Display`]: fmt::Display
/// [`format!`]: crate::format
#[unstable(feature = "os_str_display", issue = "120048")]
pub struct Display<'a> {
os_str: &'a OsStr,
}

#[unstable(feature = "os_str_display", issue = "120048")]
impl fmt::Debug for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.os_str, f)
}
}

#[unstable(feature = "os_str_display", issue = "120048")]
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.os_str.inner, f)
}
}

10 changes: 5 additions & 5 deletions library/std/src/path.rs
Original file line number Diff line number Diff line change
@@ -84,7 +84,7 @@ use crate::rc::Rc;
use crate::str::FromStr;
use crate::sync::Arc;

use crate::ffi::{OsStr, OsString};
use crate::ffi::{os_str, OsStr, OsString};
use crate::sys;
use crate::sys::path::{is_sep_byte, is_verbatim_sep, parse_prefix, MAIN_SEP_STR};

@@ -2726,7 +2726,7 @@ impl Path {
it returns an object that can be displayed"]
#[inline]
pub fn display(&self) -> Display<'_> {
Display { path: self }
Display { inner: self.inner.display() }
}

/// Queries the file system to get information about a file, directory, etc.
@@ -3033,20 +3033,20 @@ impl fmt::Debug for Path {
/// [`format!`]: crate::format
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Display<'a> {
path: &'a Path,
inner: os_str::Display<'a>,
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.path, f)
fmt::Debug::fmt(&self.inner, f)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.path.inner.display(f)
fmt::Display::fmt(&self.inner, f)
}
}

1 change: 0 additions & 1 deletion src/tools/clippy/clippy_config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@
clippy::missing_panics_doc,
rustc::diagnostic_outside_of_impl,
rustc::untranslatable_diagnostic,
rustc::untranslatable_diagnostic_trivial,
)]

extern crate rustc_ast;
2 changes: 1 addition & 1 deletion tests/rustdoc-js-std/osstring-to-string.js
Original file line number Diff line number Diff line change
@@ -4,6 +4,6 @@
const EXPECTED = {
'query': 'OsString -> String',
'others': [
{ 'path': 'std::ffi::OsString', 'name': 'into_string' },
{ 'path': 'std::ffi::os_str::OsString', 'name': 'into_string' },
]
};
19 changes: 19 additions & 0 deletions tests/rustdoc/type-alias/primitive-local-link-121106.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#![crate_name = "foo"]

#![feature(rustc_attrs)]

// @has foo/primitive.i32.html '//h1' 'Primitive Type i32'
// @has foo/index.html '//a/@href' '../foo/index.html'
#[rustc_doc_primitive = "i32"]
mod i32 {}

// @has foo/struct.Node.html '//a/@href' 'primitive.i32.html'
pub struct Node;

impl Node {
pub fn edge(&self) -> i32 { 0 }
}

// @!has foo/type.Alias.html '//a/@href' 'primitive.i32.html'
// @hasraw 'type.impl/foo/struct.Node.js' 'href=\"foo/primitive.i32.html\"'
pub type Alias = Node;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
--> $DIR/unix_sigpipe.rs:3:1
--> $DIR/unix_sigpipe-bare.rs:3:1
|
LL | #[unix_sigpipe]
| ^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#![feature(unix_sigpipe)]

#[unix_sigpipe = "sig_ign"]
#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: multiple `unix_sigpipe` attributes
--> $DIR/unix_sigpipe-different-duplicates.rs:4:1
|
LL | #[unix_sigpipe = "inherit"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unix_sigpipe-different-duplicates.rs:3:1
|
LL | #[unix_sigpipe = "sig_ign"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![feature(unix_sigpipe)]

#[unix_sigpipe = "sig_ign"]
#[unix_sigpipe = "inherit"]
#[unix_sigpipe = "inherit"] //~ error: multiple `unix_sigpipe` attributes
fn main() {}
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ LL | #[unix_sigpipe = "inherit"]
note: attribute also specified here
--> $DIR/unix_sigpipe-duplicates.rs:3:1
|
LL | #[unix_sigpipe = "sig_ign"]
LL | #[unix_sigpipe = "inherit"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error
3 changes: 3 additions & 0 deletions tests/ui/attributes/unix_sigpipe/unix_sigpipe-not-used.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//@ revisions: with_feature without_feature
//@ run-pass
//@ aux-build:sigpipe-utils.rs

#![cfg_attr(with_feature, feature(unix_sigpipe))]

fn main() {
extern crate sigpipe_utils;

13 changes: 0 additions & 13 deletions tests/ui/attributes/unix_sigpipe/unix_sigpipe-only-feature.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub struct Foo<T>(pub core::ptr::NonNull<T>);
14 changes: 14 additions & 0 deletions tests/ui/imports/import-alias-issue-121168.edition2015.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0412]: cannot find type `Foo` in this scope
--> $DIR/import-alias-issue-121168.rs:11:12
|
LL | let _: Foo<i32> = todo!();
| ^^^ not found in this scope
|
help: consider importing this struct
|
LL + use nice_crate_name::Foo;
|

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0412`.
16 changes: 16 additions & 0 deletions tests/ui/imports/import-alias-issue-121168.edition2018.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0412]: cannot find type `Foo` in this scope
--> $DIR/import-alias-issue-121168.rs:11:12
|
LL | let _: Foo<i32> = todo!();
| ^^^ not found in this scope
|
help: consider importing one of these items
|
LL + use crate::nice_crate_name::Foo;
|
LL + use import_alias_issue_121168_extern::Foo;
|

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0412`.
16 changes: 16 additions & 0 deletions tests/ui/imports/import-alias-issue-121168.edition2021.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0412]: cannot find type `Foo` in this scope
--> $DIR/import-alias-issue-121168.rs:11:12
|
LL | let _: Foo<i32> = todo!();
| ^^^ not found in this scope
|
help: consider importing one of these items
|
LL + use crate::nice_crate_name::Foo;
|
LL + use import_alias_issue_121168_extern::Foo;
|

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0412`.
14 changes: 14 additions & 0 deletions tests/ui/imports/import-alias-issue-121168.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//@ revisions: edition2015 edition2018 edition2021
//@ [edition2015] edition:2015
//@ [edition2018] edition:2018
//@ [edition2021] edition:2021
//@ compile-flags: --extern import_alias_issue_121168_extern
//@ aux-build: import-alias-issue-121168-extern.rs

extern crate import_alias_issue_121168_extern as nice_crate_name;

fn use_foo_from_another_crate_without_importing_it_first() {
let _: Foo<i32> = todo!(); //~ ERROR cannot find type `Foo` in this scope
}

fn main() {}