Skip to content

Commit f942d8d

Browse files
committed
Using required dep as a feature is a warning for now, not an error
1 parent 5cab69c commit f942d8d

File tree

5 files changed

+59
-23
lines changed

5 files changed

+59
-23
lines changed

src/cargo/core/resolver/mod.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ use url::Url;
5757

5858
use core::{PackageId, Registry, SourceId, Summary, Dependency};
5959
use core::PackageIdSpec;
60+
use core::shell::Shell;
6061
use util::Graph;
6162
use util::errors::{CargoResult, CargoError};
6263
use util::profile;
@@ -330,20 +331,25 @@ struct Context<'a> {
330331
resolve_replacements: RcList<(PackageId, PackageId)>,
331332

332333
replacements: &'a [(PackageIdSpec, Dependency)],
334+
335+
// These warnings are printed after resolution.
336+
warnings: RcList<String>,
333337
}
334338

335339
type Activations = HashMap<String, HashMap<SourceId, Vec<Summary>>>;
336340

337341
/// Builds the list of all packages required to build the first argument.
338342
pub fn resolve(summaries: &[(Summary, Method)],
339343
replacements: &[(PackageIdSpec, Dependency)],
340-
registry: &mut Registry) -> CargoResult<Resolve> {
344+
registry: &mut Registry,
345+
shell: Option<&mut Shell>) -> CargoResult<Resolve> {
341346
let cx = Context {
342347
resolve_graph: RcList::new(),
343348
resolve_features: HashMap::new(),
344349
resolve_replacements: RcList::new(),
345350
activations: HashMap::new(),
346351
replacements: replacements,
352+
warnings: RcList::new(),
347353
};
348354
let _p = profile::start(format!("resolving"));
349355
let cx = activate_deps_loop(cx, registry, summaries)?;
@@ -368,8 +374,17 @@ pub fn resolve(summaries: &[(Summary, Method)],
368374
}
369375

370376
check_cycles(&resolve, &cx.activations)?;
371-
372377
trace!("resolved: {:?}", resolve);
378+
379+
// If we have a shell, emit warnings about required deps used as feature.
380+
if let Some(shell) = shell {
381+
let mut warnings = &cx.warnings;
382+
while let Some(ref head) = warnings.head {
383+
shell.warn(&head.0)?;
384+
warnings = &head.1;
385+
}
386+
}
387+
373388
Ok(resolve)
374389
}
375390

@@ -1088,9 +1103,13 @@ impl<'a> Context<'a> {
10881103
// to `ret`.
10891104
let base = feature_deps.remove(dep.name()).unwrap_or((false, vec![]));
10901105
if !dep.is_optional() && base.0 {
1091-
bail!("Package `{}` does not have feature `{}`. It has a required dependency with \
1092-
that name, but only optional dependencies can be used as features.",
1093-
s.package_id(), dep.name());
1106+
self.warnings.push(
1107+
format!("Package `{}` does not have feature `{}`. It has a required dependency \
1108+
with that name, but only optional dependencies can be used as features. \
1109+
This is currently a warning to ease the transition, but it will become an \
1110+
error in the future.",
1111+
s.package_id(), dep.name())
1112+
);
10941113
}
10951114
let mut base = base.1;
10961115
base.extend(dep.features().iter().cloned());

src/cargo/ops/cargo_generate_lockfile.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn generate_lockfile(ws: &Workspace) -> CargoResult<()> {
1919
let mut registry = PackageRegistry::new(ws.config())?;
2020
let resolve = ops::resolve_with_previous(&mut registry, ws,
2121
Method::Everything,
22-
None, None, &[])?;
22+
None, None, &[], true)?;
2323
ops::write_pkg_lockfile(ws, &resolve)?;
2424
Ok(())
2525
}
@@ -79,7 +79,8 @@ pub fn update_lockfile(ws: &Workspace, opts: &UpdateOptions)
7979
Method::Everything,
8080
Some(&previous_resolve),
8181
Some(&to_avoid),
82-
&[])?;
82+
&[],
83+
true)?;
8384

8485
// Summarize what is changing for the user.
8586
let print_change = |status: &str, msg: String| {

src/cargo/ops/resolve.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use util::errors::{CargoResult, CargoResultExt};
1515
/// lockfile.
1616
pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolve)> {
1717
let mut registry = PackageRegistry::new(ws.config())?;
18-
let resolve = resolve_with_registry(ws, &mut registry)?;
18+
let resolve = resolve_with_registry(ws, &mut registry, true)?;
1919
let packages = get_resolved_packages(&resolve, registry);
2020
Ok((packages, resolve))
2121
}
@@ -44,7 +44,7 @@ pub fn resolve_ws_precisely<'a>(ws: &Workspace<'a>,
4444
let resolve = if ws.require_optional_deps() {
4545
// First, resolve the root_package's *listed* dependencies, as well as
4646
// downloading and updating all remotes and such.
47-
let resolve = resolve_with_registry(ws, &mut registry)?;
47+
let resolve = resolve_with_registry(ws, &mut registry, false)?;
4848

4949
// Second, resolve with precisely what we're doing. Filter out
5050
// transitive dependencies if necessary, specify features, handle
@@ -79,19 +79,19 @@ pub fn resolve_ws_precisely<'a>(ws: &Workspace<'a>,
7979
let resolved_with_overrides =
8080
ops::resolve_with_previous(&mut registry, ws,
8181
method, resolve.as_ref(), None,
82-
specs)?;
82+
specs, true)?;
8383

8484
let packages = get_resolved_packages(&resolved_with_overrides, registry);
8585

8686
Ok((packages, resolved_with_overrides))
8787
}
8888

89-
fn resolve_with_registry(ws: &Workspace, registry: &mut PackageRegistry)
89+
fn resolve_with_registry(ws: &Workspace, registry: &mut PackageRegistry, warn: bool)
9090
-> CargoResult<Resolve> {
9191
let prev = ops::load_pkg_lockfile(ws)?;
9292
let resolve = resolve_with_previous(registry, ws,
9393
Method::Everything,
94-
prev.as_ref(), None, &[])?;
94+
prev.as_ref(), None, &[], warn)?;
9595

9696
if !ws.is_ephemeral() {
9797
ops::write_pkg_lockfile(ws, &resolve)?;
@@ -114,7 +114,8 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry,
114114
method: Method,
115115
previous: Option<&'a Resolve>,
116116
to_avoid: Option<&HashSet<&'a PackageId>>,
117-
specs: &[PackageIdSpec])
117+
specs: &[PackageIdSpec],
118+
warn: bool)
118119
-> CargoResult<Resolve> {
119120
// Here we place an artificial limitation that all non-registry sources
120121
// cannot be locked at more than one revision. This means that if a git
@@ -256,9 +257,17 @@ pub fn resolve_with_previous<'a>(registry: &mut PackageRegistry,
256257
None => root_replace.to_vec(),
257258
};
258259

260+
let mut shell;
261+
let opt_shell = if warn {
262+
shell = ws.config().shell();
263+
Some(&mut *shell)
264+
} else {
265+
None
266+
};
259267
let mut resolved = resolver::resolve(&summaries,
260268
&replace,
261-
registry)?;
269+
registry,
270+
opt_shell)?;
262271
resolved.register_used_patches(registry.patches());
263272
if let Some(previous) = previous {
264273
resolved.merge_from(previous)?;

tests/features.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ fn invalid9() {
237237
[dependencies.bar]
238238
path = "bar"
239239
"#)
240-
.file("src/main.rs", "")
240+
.file("src/main.rs", "fn main() {}")
241241
.file("bar/Cargo.toml", r#"
242242
[package]
243243
name = "bar"
@@ -247,9 +247,12 @@ fn invalid9() {
247247
.file("bar/src/lib.rs", "");
248248

249249
assert_that(p.cargo_process("build").arg("--features").arg("bar"),
250-
execs().with_status(101).with_stderr("\
251-
[ERROR] Package `foo v0.0.1 ([..])` does not have feature `bar`. It has a required dependency with \
252-
that name, but only optional dependencies can be used as features.
250+
execs().with_status(0).with_stderr("\
251+
warning: Package `foo v0.0.1 ([..])` does not have feature `bar`. It has a required dependency with \
252+
that name, but only optional dependencies can be used as features. [..]
253+
Compiling bar v0.0.1 ([..])
254+
Compiling foo v0.0.1 ([..])
255+
Finished dev [unoptimized + debuginfo] target(s) in [..] secs
253256
"));
254257
}
255258

@@ -266,7 +269,7 @@ fn invalid10() {
266269
path = "bar"
267270
features = ["baz"]
268271
"#)
269-
.file("src/main.rs", "")
272+
.file("src/main.rs", "fn main() {}")
270273
.file("bar/Cargo.toml", r#"
271274
[package]
272275
name = "bar"
@@ -286,9 +289,13 @@ fn invalid10() {
286289
.file("bar/baz/src/lib.rs", "");
287290

288291
assert_that(p.cargo_process("build"),
289-
execs().with_status(101).with_stderr("\
290-
[ERROR] Package `bar v0.0.1 ([..])` does not have feature `baz`. It has a required dependency with \
291-
that name, but only optional dependencies can be used as features.
292+
execs().with_status(0).with_stderr("\
293+
warning: Package `bar v0.0.1 ([..])` does not have feature `baz`. It has a required dependency with \
294+
that name, but only optional dependencies can be used as features. [..]
295+
Compiling baz v0.0.1 ([..])
296+
Compiling bar v0.0.1 ([..])
297+
Compiling foo v0.0.1 ([..])
298+
Finished dev [unoptimized + debuginfo] target(s) in [..] secs
292299
"));
293300
}
294301

tests/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ fn resolve(pkg: PackageId, deps: Vec<Dependency>, registry: &[Summary])
3232
let mut registry = MyRegistry(registry);
3333
let summary = Summary::new(pkg.clone(), deps, HashMap::new()).unwrap();
3434
let method = Method::Everything;
35-
let resolve = resolver::resolve(&[(summary, method)], &[], &mut registry)?;
35+
let resolve = resolver::resolve(&[(summary, method)], &[], &mut registry, None)?;
3636
let res = resolve.iter().cloned().collect();
3737
Ok(res)
3838
}

0 commit comments

Comments
 (0)