@@ -5,7 +5,7 @@ use crate::core::compiler::UnitInterner;
55use crate :: core:: compiler:: { CompileKind , CompileMode , RustcTargetData , Unit } ;
66use crate :: core:: profiles:: { Profiles , UnitFor } ;
77use crate :: core:: resolver:: features:: { CliFeatures , FeaturesFor , ResolvedFeatures } ;
8- use crate :: core:: resolver:: HasDevUnits ;
8+ use crate :: core:: resolver:: { EncodableResolve , HasDevUnits } ;
99use crate :: core:: { Dependency , PackageId , PackageSet , Resolve , SourceId , Workspace } ;
1010use crate :: ops:: { self , Packages } ;
1111use crate :: util:: errors:: CargoResult ;
@@ -125,9 +125,12 @@ pub fn resolve_std<'gctx>(
125125 // now. Perhaps in the future features will be decoupled from the resolver
126126 // and it will be easier to control feature selection.
127127 let current_manifest = src_path. join ( "library/sysroot/Cargo.toml" ) ;
128- // TODO: Consider doing something to enforce --locked? Or to prevent the
129- // lock file from being written, such as setting ephemeral.
130- let mut std_ws = Workspace :: new_virtual ( src_path, current_manifest, virtual_manifest, gctx) ?;
128+ let mut std_ws =
129+ Workspace :: new_virtual ( src_path. clone ( ) , current_manifest, virtual_manifest, gctx) ?;
130+
131+ // The source checkout isn't managed by us, so setting ephemeral here
132+ // ensures the lockfile isn't updated.
133+ std_ws. set_ephemeral ( true ) ;
131134 // Don't require optional dependencies in this workspace, aka std's own
132135 // `[dev-dependencies]`. No need for us to generate a `Resolve` which has
133136 // those included because we'll never use them anyway.
@@ -158,6 +161,47 @@ pub fn resolve_std<'gctx>(
158161 HasDevUnits :: No ,
159162 crate :: core:: resolver:: features:: ForceAllTargets :: No ,
160163 ) ?;
164+
165+ // Verify that we have resolved to a subset of the lockfile
166+ let lockfile = std:: fs:: read_to_string ( & src_path. join ( "Cargo.lock" ) )
167+ . expect ( "Couldn't read the Rust source's lockfile" ) ;
168+
169+ let encoded_lockfile: EncodableResolve = toml:: from_str ( & lockfile) . unwrap ( ) ;
170+ let lockfile_packages = encoded_lockfile. package ( ) . expect ( "libstd has no packages!" ) ;
171+
172+ for resolved_pkg in resolve. targeted_resolve . iter ( ) {
173+ let pkg_name = resolved_pkg. name ( ) . to_string ( ) ;
174+ let pkg_ver = resolved_pkg. version ( ) . to_string ( ) ;
175+ let lockfile_pkg = lockfile_packages. binary_search_by_key (
176+ & ( pkg_name. as_str ( ) , pkg_ver. as_str ( ) ) ,
177+ |p| ( p. name ( ) , p. version ( ) )
178+ )
179+ . and_then ( |idx| Ok ( & lockfile_packages[ idx] ) )
180+ . unwrap_or_else ( |_|
181+ panic ! ( "Standard library's package graph changed during resolution:
182+ Package '{}' ({}) was present in the resolve but not in the original lockfile" ,
183+ resolved_pkg. name( ) , resolved_pkg. version( ) )
184+ ) ;
185+ // If the lockfile wasn't sorted then the binary search result can be nonsensical
186+ assert ! ( lockfile_pkg. name( ) == pkg_name) ;
187+
188+ for ( dep, _) in resolve. targeted_resolve . deps ( resolved_pkg) {
189+ lockfile_pkg. dependencies ( )
190+ . and_then ( |deps| {
191+ deps. iter ( ) . find ( |pkg| {
192+ pkg. name ( ) == dep. name ( ) . as_str ( )
193+ && ( pkg. version ( ) == None
194+ || pkg. version ( ) == Some ( dep. version ( ) . to_string ( ) . as_str ( ) ) )
195+ } )
196+ } )
197+ . unwrap_or_else ( ||
198+ panic ! ( "Standard library's package graph changed during resolution:
199+ Package '{}' ({}) was present as a dependency of '{} ({}) in the resolve but not in the lockfile" ,
200+ dep. name( ) , dep. version( ) , resolved_pkg. name( ) , resolved_pkg. version( ) )
201+ ) ;
202+ }
203+ }
204+
161205 Ok ( (
162206 resolve. pkg_set ,
163207 resolve. targeted_resolve ,
0 commit comments